Merge pull request #11796 from afirago/fix-fallthrough-werror

Fix implicit fallthrough warning on GCC 7.x
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..094e43e
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,6 @@
+# Auto-generated by the tools/mkowners/mkowners.py tool
+# Uses OWNERS files in different modules throughout the
+# repository as the source of truth for module ownership.
+/**/OWNERS @markdroth @nicolasnoble @ctiller
+/bazel/** @nicolasnoble @dgquintas @ctiller
+/src/core/ext/filters/client_channel/** @markdroth @dgquintas @ctiller
diff --git a/.pylintrc b/.pylintrc
index 8447821..05b4e68 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -41,6 +41,11 @@
 	# 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,
diff --git a/BUILD b/BUILD
index 495bb66..6b49973 100644
--- a/BUILD
+++ b/BUILD
@@ -40,9 +40,154 @@
 
 version = "1.5.0-dev"
 
+GPR_PUBLIC_HDRS = [
+    "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/avl.h",
+    "include/grpc/support/cmdline.h",
+    "include/grpc/support/cpu.h",
+    "include/grpc/support/histogram.h",
+    "include/grpc/support/host_port.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/subprocess.h",
+    "include/grpc/support/sync.h",
+    "include/grpc/support/sync_generic.h",
+    "include/grpc/support/sync_posix.h",
+    "include/grpc/support/sync_windows.h",
+    "include/grpc/support/thd.h",
+    "include/grpc/support/time.h",
+    "include/grpc/support/tls.h",
+    "include/grpc/support/tls_gcc.h",
+    "include/grpc/support/tls_msvc.h",
+    "include/grpc/support/tls_pthread.h",
+    "include/grpc/support/useful.h",
+]
+
+GRPC_PUBLIC_HDRS = [
+    "include/grpc/byte_buffer.h",
+    "include/grpc/byte_buffer_reader.h",
+    "include/grpc/compression.h",
+    "include/grpc/load_reporting.h",
+    "include/grpc/grpc.h",
+    "include/grpc/grpc_posix.h",
+    "include/grpc/grpc_security_constants.h",
+    "include/grpc/slice.h",
+    "include/grpc/slice_buffer.h",
+    "include/grpc/status.h",
+    "include/grpc/support/workaround_list.h",
+]
+
+GRPC_SECURE_PUBLIC_HDRS = [
+    "include/grpc/grpc_security.h",
+]
+
+# TODO(ctiller): layer grpc atop grpc_unsecure, layer grpc++ atop grpc++_unsecure
+GRPCXX_SRCS = [
+    "src/cpp/client/channel_cc.cc",
+    "src/cpp/client/client_context.cc",
+    "src/cpp/client/create_channel.cc",
+    "src/cpp/client/create_channel_internal.cc",
+    "src/cpp/client/create_channel_posix.cc",
+    "src/cpp/client/credentials_cc.cc",
+    "src/cpp/client/generic_stub.cc",
+    "src/cpp/common/channel_arguments.cc",
+    "src/cpp/common/channel_filter.cc",
+    "src/cpp/common/completion_queue_cc.cc",
+    "src/cpp/common/core_codegen.cc",
+    "src/cpp/common/resource_quota_cc.cc",
+    "src/cpp/common/rpc_method.cc",
+    "src/cpp/common/version_cc.cc",
+    "src/cpp/server/async_generic_service.cc",
+    "src/cpp/server/channel_argument_option.cc",
+    "src/cpp/server/create_default_thread_pool.cc",
+    "src/cpp/server/dynamic_thread_pool.cc",
+    "src/cpp/server/health/default_health_check_service.cc",
+    "src/cpp/server/health/health.pb.c",
+    "src/cpp/server/health/health_check_service.cc",
+    "src/cpp/server/health/health_check_service_server_builder_option.cc",
+    "src/cpp/server/server_builder.cc",
+    "src/cpp/server/server_cc.cc",
+    "src/cpp/server/server_context.cc",
+    "src/cpp/server/server_credentials.cc",
+    "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",
+]
+
+GRPCXX_HDRS = [
+    "src/cpp/client/create_channel_internal.h",
+    "src/cpp/common/channel_filter.h",
+    "src/cpp/server/dynamic_thread_pool.h",
+    "src/cpp/server/health/default_health_check_service.h",
+    "src/cpp/server/health/health.pb.h",
+    "src/cpp/server/thread_pool_interface.h",
+    "src/cpp/thread_manager/thread_manager.h",
+]
+
+GRPCXX_PUBLIC_HDRS = [
+    "include/grpc++/alarm.h",
+    "include/grpc++/channel.h",
+    "include/grpc++/client_context.h",
+    "include/grpc++/completion_queue.h",
+    "include/grpc++/create_channel.h",
+    "include/grpc++/create_channel_posix.h",
+    "include/grpc++/ext/health_check_service_server_builder_option.h",
+    "include/grpc++/generic/async_generic_service.h",
+    "include/grpc++/generic/generic_stub.h",
+    "include/grpc++/grpc++.h",
+    "include/grpc++/health_check_service_interface.h",
+    "include/grpc++/impl/call.h",
+    "include/grpc++/impl/channel_argument_option.h",
+    "include/grpc++/impl/client_unary_call.h",
+    "include/grpc++/impl/codegen/core_codegen.h",
+    "include/grpc++/impl/grpc_library.h",
+    "include/grpc++/impl/method_handler_impl.h",
+    "include/grpc++/impl/rpc_method.h",
+    "include/grpc++/impl/rpc_service_method.h",
+    "include/grpc++/impl/serialization_traits.h",
+    "include/grpc++/impl/server_builder_option.h",
+    "include/grpc++/impl/server_builder_plugin.h",
+    "include/grpc++/impl/server_initializer.h",
+    "include/grpc++/impl/service_type.h",
+    "include/grpc++/impl/sync_cxx11.h",
+    "include/grpc++/impl/sync_no_cxx11.h",
+    "include/grpc++/resource_quota.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
+    "include/grpc++/server.h",
+    "include/grpc++/server_builder.h",
+    "include/grpc++/server_context.h",
+    "include/grpc++/server_posix.h",
+    "include/grpc++/support/async_stream.h",
+    "include/grpc++/support/async_unary_call.h",
+    "include/grpc++/support/byte_buffer.h",
+    "include/grpc++/support/channel_arguments.h",
+    "include/grpc++/support/config.h",
+    "include/grpc++/support/slice.h",
+    "include/grpc++/support/status.h",
+    "include/grpc++/support/status_code_enum.h",
+    "include/grpc++/support/string_ref.h",
+    "include/grpc++/support/stub_options.h",
+    "include/grpc++/support/sync_stream.h",
+    "include/grpc++/support/time.h",
+]
+
 grpc_cc_library(
     name = "gpr",
     language = "c",
+    public_hdrs = GPR_PUBLIC_HDRS,
     standalone = True,
     deps = [
         "gpr_base",
@@ -57,9 +202,11 @@
         "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
     ],
     language = "c",
+    public_hdrs = GRPC_PUBLIC_HDRS,
     standalone = True,
     deps = [
         "grpc_common",
+        "grpc_lb_policy_grpclb",
     ],
 )
 
@@ -70,11 +217,11 @@
         "src/core/plugin_registry/grpc_plugin_registry.c",
     ],
     language = "c",
+    public_hdrs = GRPC_PUBLIC_HDRS + GRPC_SECURE_PUBLIC_HDRS,
     standalone = True,
     deps = [
         "grpc_common",
         "grpc_lb_policy_grpclb_secure",
-        "grpc_resolver_dns_ares",
         "grpc_secure",
         "grpc_transport_chttp2_client_secure",
         "grpc_transport_chttp2_server_secure",
@@ -114,6 +261,7 @@
         "src/cpp/server/secure_server_credentials.h",
     ],
     language = "c++",
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     standalone = True,
     deps = [
         "gpr",
@@ -139,6 +287,7 @@
         "grpc++_base_unsecure",
         "grpc++_codegen_base",
         "grpc++_codegen_base_src",
+        "grpc++_codegen_proto",
         "grpc_unsecure",
     ],
 )
@@ -379,34 +528,7 @@
         "src/core/lib/support/tmpfile.h",
     ],
     language = "c",
-    public_hdrs = [
-        "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/avl.h",
-        "include/grpc/support/cmdline.h",
-        "include/grpc/support/cpu.h",
-        "include/grpc/support/histogram.h",
-        "include/grpc/support/host_port.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/subprocess.h",
-        "include/grpc/support/sync.h",
-        "include/grpc/support/sync_generic.h",
-        "include/grpc/support/sync_posix.h",
-        "include/grpc/support/sync_windows.h",
-        "include/grpc/support/thd.h",
-        "include/grpc/support/time.h",
-        "include/grpc/support/tls.h",
-        "include/grpc/support/tls_gcc.h",
-        "include/grpc/support/tls_msvc.h",
-        "include/grpc/support/tls_pthread.h",
-        "include/grpc/support/useful.h",
-    ],
+    public_hdrs = GPR_PUBLIC_HDRS,
     deps = [
         "gpr_codegen",
     ],
@@ -434,6 +556,7 @@
     name = "grpc_trace",
     srcs = ["src/core/lib/debug/trace.c"],
     hdrs = ["src/core/lib/debug/trace.h"],
+    language = "c",
     deps = [":gpr"],
 )
 
@@ -449,6 +572,7 @@
         "src/core/lib/channel/handshaker_registry.c",
         "src/core/lib/compression/compression.c",
         "src/core/lib/compression/message_compress.c",
+        "src/core/lib/compression/stream_compression.c",
         "src/core/lib/http/format_request.c",
         "src/core/lib/http/httpcli.c",
         "src/core/lib/http/parser.c",
@@ -575,6 +699,7 @@
         "src/core/lib/channel/handshaker_registry.h",
         "src/core/lib/compression/algorithm_metadata.h",
         "src/core/lib/compression/message_compress.h",
+        "src/core/lib/compression/stream_compression.h",
         "src/core/lib/http/format_request.h",
         "src/core/lib/http/httpcli.h",
         "src/core/lib/http/parser.h",
@@ -597,9 +722,11 @@
         "src/core/lib/iomgr/iomgr.h",
         "src/core/lib/iomgr/iomgr_internal.h",
         "src/core/lib/iomgr/iomgr_posix.h",
+        "src/core/lib/iomgr/iomgr_uv.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",
@@ -679,19 +806,7 @@
         "zlib",
     ],
     language = "c",
-    public_hdrs = [
-        "include/grpc/byte_buffer.h",
-        "include/grpc/byte_buffer_reader.h",
-        "include/grpc/compression.h",
-        "include/grpc/load_reporting.h",
-        "include/grpc/grpc.h",
-        "include/grpc/grpc_posix.h",
-        "include/grpc/grpc_security_constants.h",
-        "include/grpc/slice.h",
-        "include/grpc/slice_buffer.h",
-        "include/grpc/status.h",
-        "include/grpc/support/workaround_list.h",
-    ],
+    public_hdrs = GRPC_PUBLIC_HDRS,
     deps = [
         "gpr_base",
         "grpc_codegen",
@@ -712,6 +827,7 @@
 
 grpc_cc_library(
     name = "grpc_common",
+    language = "c",
     deps = [
         "grpc_base",
         # standard plugins
@@ -722,10 +838,13 @@
         "grpc_load_reporting",
         "grpc_max_age_filter",
         "grpc_message_size_filter",
+        "grpc_resolver_dns_ares",
+        "grpc_resolver_fake",
         "grpc_resolver_dns_native",
         "grpc_resolver_sockaddr",
         "grpc_transport_chttp2_client_insecure",
         "grpc_transport_chttp2_server_insecure",
+        "grpc_transport_inproc",
         "grpc_workaround_cronet_compression_filter",
         "grpc_server_backward_compatibility",
     ],
@@ -1083,9 +1202,7 @@
         "src/core/lib/security/util/json_util.h",
     ],
     language = "c",
-    public_hdrs = [
-        "include/grpc/grpc_security.h",
-    ],
+    public_hdrs = GRPC_SECURE_PUBLIC_HDRS,
     deps = [
         "grpc_base",
         "grpc_transport_chttp2_alpn",
@@ -1100,6 +1217,7 @@
         "src/core/ext/transport/chttp2/transport/bin_encoder.c",
         "src/core/ext/transport/chttp2/transport/chttp2_plugin.c",
         "src/core/ext/transport/chttp2/transport/chttp2_transport.c",
+        "src/core/ext/transport/chttp2/transport/flow_control.c",
         "src/core/ext/transport/chttp2/transport/frame_data.c",
         "src/core/ext/transport/chttp2/transport/frame_goaway.c",
         "src/core/ext/transport/chttp2/transport/frame_ping.c",
@@ -1274,15 +1392,32 @@
 )
 
 grpc_cc_library(
+    name = "grpc_transport_inproc",
+    srcs = [
+        "src/core/ext/transport/inproc/inproc_plugin.c",
+        "src/core/ext/transport/inproc/inproc_transport.c",
+    ],
+    hdrs = [
+        "src/core/ext/transport/inproc/inproc_transport.h",
+    ],
+    language = "c",
+    deps = [
+        "grpc_base",
+    ],
+)
+
+grpc_cc_library(
     name = "tsi",
     srcs = [
         "src/core/tsi/fake_transport_security.c",
+        "src/core/tsi/gts_transport_security.c",
         "src/core/tsi/ssl_transport_security.c",
         "src/core/tsi/transport_security.c",
         "src/core/tsi/transport_security_adapter.c",
     ],
     hdrs = [
         "src/core/tsi/fake_transport_security.h",
+        "src/core/tsi/gts_transport_security.h",
         "src/core/tsi/ssl_transport_security.h",
         "src/core/tsi/ssl_types.h",
         "src/core/tsi/transport_security.h",
@@ -1295,107 +1430,11 @@
     language = "c",
     deps = [
         "gpr",
+        "grpc_base",
         "grpc_trace",
     ],
 )
 
-# TODO(ctiller): layer grpc atop grpc_unsecure, layer grpc++ atop grpc++_unsecure
-GRPCXX_SRCS = [
-    "src/cpp/client/channel_cc.cc",
-    "src/cpp/client/client_context.cc",
-    "src/cpp/client/create_channel.cc",
-    "src/cpp/client/create_channel_internal.cc",
-    "src/cpp/client/create_channel_posix.cc",
-    "src/cpp/client/credentials_cc.cc",
-    "src/cpp/client/generic_stub.cc",
-    "src/cpp/common/channel_arguments.cc",
-    "src/cpp/common/channel_filter.cc",
-    "src/cpp/common/completion_queue_cc.cc",
-    "src/cpp/common/core_codegen.cc",
-    "src/cpp/common/resource_quota_cc.cc",
-    "src/cpp/common/rpc_method.cc",
-    "src/cpp/common/version_cc.cc",
-    "src/cpp/server/async_generic_service.cc",
-    "src/cpp/server/channel_argument_option.cc",
-    "src/cpp/server/create_default_thread_pool.cc",
-    "src/cpp/server/dynamic_thread_pool.cc",
-    "src/cpp/server/health/default_health_check_service.cc",
-    "src/cpp/server/health/health.pb.c",
-    "src/cpp/server/health/health_check_service.cc",
-    "src/cpp/server/health/health_check_service_server_builder_option.cc",
-    "src/cpp/server/server_builder.cc",
-    "src/cpp/server/server_cc.cc",
-    "src/cpp/server/server_context.cc",
-    "src/cpp/server/server_credentials.cc",
-    "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",
-]
-
-GRPCXX_HDRS = [
-    "src/cpp/client/create_channel_internal.h",
-    "src/cpp/common/channel_filter.h",
-    "src/cpp/server/dynamic_thread_pool.h",
-    "src/cpp/server/health/default_health_check_service.h",
-    "src/cpp/server/health/health.pb.h",
-    "src/cpp/server/thread_pool_interface.h",
-    "src/cpp/thread_manager/thread_manager.h",
-]
-
-GRPCXX_PUBLIC_HDRS = [
-    "include/grpc++/alarm.h",
-    "include/grpc++/channel.h",
-    "include/grpc++/client_context.h",
-    "include/grpc++/completion_queue.h",
-    "include/grpc++/create_channel.h",
-    "include/grpc++/create_channel_posix.h",
-    "include/grpc++/ext/health_check_service_server_builder_option.h",
-    "include/grpc++/generic/async_generic_service.h",
-    "include/grpc++/generic/generic_stub.h",
-    "include/grpc++/grpc++.h",
-    "include/grpc++/health_check_service_interface.h",
-    "include/grpc++/impl/call.h",
-    "include/grpc++/impl/channel_argument_option.h",
-    "include/grpc++/impl/client_unary_call.h",
-    "include/grpc++/impl/codegen/core_codegen.h",
-    "include/grpc++/impl/grpc_library.h",
-    "include/grpc++/impl/method_handler_impl.h",
-    "include/grpc++/impl/rpc_method.h",
-    "include/grpc++/impl/rpc_service_method.h",
-    "include/grpc++/impl/serialization_traits.h",
-    "include/grpc++/impl/server_builder_option.h",
-    "include/grpc++/impl/server_builder_plugin.h",
-    "include/grpc++/impl/server_initializer.h",
-    "include/grpc++/impl/service_type.h",
-    "include/grpc++/impl/sync_cxx11.h",
-    "include/grpc++/impl/sync_no_cxx11.h",
-    "include/grpc++/resource_quota.h",
-    "include/grpc++/security/auth_context.h",
-    "include/grpc++/security/auth_metadata_processor.h",
-    "include/grpc++/security/credentials.h",
-    "include/grpc++/security/server_credentials.h",
-    "include/grpc++/server.h",
-    "include/grpc++/server_builder.h",
-    "include/grpc++/server_context.h",
-    "include/grpc++/server_posix.h",
-    "include/grpc++/support/async_stream.h",
-    "include/grpc++/support/async_unary_call.h",
-    "include/grpc++/support/byte_buffer.h",
-    "include/grpc++/support/channel_arguments.h",
-    "include/grpc++/support/config.h",
-    "include/grpc++/support/slice.h",
-    "include/grpc++/support/status.h",
-    "include/grpc++/support/status_code_enum.h",
-    "include/grpc++/support/string_ref.h",
-    "include/grpc++/support/stub_options.h",
-    "include/grpc++/support/sync_stream.h",
-    "include/grpc++/support/time.h",
-]
-
 grpc_cc_library(
     name = "grpc++_base",
     srcs = GRPCXX_SRCS,
@@ -1510,6 +1549,7 @@
         ":grpc++",
         "//src/proto/grpc/reflection/v1alpha:reflection_proto",
     ],
+    alwayslink = 1,
 )
 
 grpc_cc_library(
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b535d7f..6e1b471 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -394,6 +394,7 @@
 add_dependencies(buildtests_c bdp_estimator_test)
 add_dependencies(buildtests_c bin_decoder_test)
 add_dependencies(buildtests_c bin_encoder_test)
+add_dependencies(buildtests_c byte_stream_test)
 add_dependencies(buildtests_c census_context_test)
 add_dependencies(buildtests_c census_intrusive_hash_map_test)
 add_dependencies(buildtests_c census_resource_test)
@@ -528,6 +529,7 @@
 add_dependencies(buildtests_c socket_utils_test)
 endif()
 add_dependencies(buildtests_c status_conversion_test)
+add_dependencies(buildtests_c stream_compression_test)
 add_dependencies(buildtests_c stream_owned_slice_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_c tcp_client_posix_test)
@@ -599,6 +601,7 @@
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_c h2_uds_test)
 endif()
+add_dependencies(buildtests_c inproc_test)
 add_dependencies(buildtests_c h2_census_nosec_test)
 add_dependencies(buildtests_c h2_compress_nosec_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -619,6 +622,7 @@
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_c h2_uds_nosec_test)
 endif()
+add_dependencies(buildtests_c inproc_nosec_test)
 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)
@@ -748,6 +752,7 @@
 add_dependencies(buildtests_cxx server_crash_test)
 endif()
 add_dependencies(buildtests_cxx server_crash_test_client)
+add_dependencies(buildtests_cxx server_request_call_test)
 add_dependencies(buildtests_cxx shutdown_test)
 add_dependencies(buildtests_cxx status_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -952,6 +957,7 @@
   src/core/lib/channel/handshaker_registry.c
   src/core/lib/compression/compression.c
   src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
   src/core/lib/http/format_request.c
   src/core/lib/http/httpcli.c
   src/core/lib/http/parser.c
@@ -1073,6 +1079,7 @@
   src/core/ext/transport/chttp2/transport/bin_encoder.c
   src/core/ext/transport/chttp2/transport/chttp2_plugin.c
   src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
   src/core/ext/transport/chttp2/transport/frame_data.c
   src/core/ext/transport/chttp2/transport/frame_goaway.c
   src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -1120,6 +1127,7 @@
   src/core/lib/security/util/json_util.c
   src/core/lib/surface/init_secure.c
   src/core/tsi/fake_transport_security.c
+  src/core/tsi/gts_transport_security.c
   src/core/tsi/ssl_transport_security.c
   src/core/tsi/transport_security.c
   src/core/tsi/transport_security_adapter.c
@@ -1151,6 +1159,8 @@
   src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
   src/core/ext/transport/chttp2/client/insecure/channel_create.c
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
+  src/core/ext/transport/inproc/inproc_plugin.c
+  src/core/ext/transport/inproc/inproc_transport.c
   src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c
   src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
   src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c
@@ -1230,17 +1240,6 @@
 )
 
 foreach(_hdr
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.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/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
@@ -1261,6 +1260,17 @@
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
   include/grpc/grpc_security.h
+  include/grpc/byte_buffer.h
+  include/grpc/byte_buffer_reader.h
+  include/grpc/compression.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/census.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
@@ -1291,6 +1301,7 @@
   src/core/lib/channel/handshaker_registry.c
   src/core/lib/compression/compression.c
   src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
   src/core/lib/http/format_request.c
   src/core/lib/http/httpcli.c
   src/core/lib/http/parser.c
@@ -1415,6 +1426,7 @@
   src/core/ext/transport/chttp2/transport/bin_encoder.c
   src/core/ext/transport/chttp2/transport/chttp2_plugin.c
   src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
   src/core/ext/transport/chttp2/transport/frame_data.c
   src/core/ext/transport/chttp2/transport/frame_goaway.c
   src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -1483,6 +1495,7 @@
   src/core/lib/security/util/json_util.c
   src/core/lib/surface/init_secure.c
   src/core/tsi/fake_transport_security.c
+  src/core/tsi/gts_transport_security.c
   src/core/tsi/ssl_transport_security.c
   src/core/tsi/transport_security.c
   src/core/tsi/transport_security_adapter.c
@@ -1529,17 +1542,6 @@
 )
 
 foreach(_hdr
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.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/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
@@ -1561,6 +1563,7 @@
   include/grpc/impl/codegen/sync_windows.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)
@@ -1610,6 +1613,7 @@
   src/core/lib/channel/handshaker_registry.c
   src/core/lib/compression/compression.c
   src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
   src/core/lib/http/format_request.c
   src/core/lib/http/httpcli.c
   src/core/lib/http/parser.c
@@ -1726,6 +1730,54 @@
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
   src/core/lib/debug/trace.c
+  src/core/ext/filters/client_channel/channel_connectivity.c
+  src/core/ext/filters/client_channel/client_channel.c
+  src/core/ext/filters/client_channel/client_channel_factory.c
+  src/core/ext/filters/client_channel/client_channel_plugin.c
+  src/core/ext/filters/client_channel/connector.c
+  src/core/ext/filters/client_channel/http_connect_handshaker.c
+  src/core/ext/filters/client_channel/http_proxy.c
+  src/core/ext/filters/client_channel/lb_policy.c
+  src/core/ext/filters/client_channel/lb_policy_factory.c
+  src/core/ext/filters/client_channel/lb_policy_registry.c
+  src/core/ext/filters/client_channel/parse_address.c
+  src/core/ext/filters/client_channel/proxy_mapper.c
+  src/core/ext/filters/client_channel/proxy_mapper_registry.c
+  src/core/ext/filters/client_channel/resolver.c
+  src/core/ext/filters/client_channel/resolver_factory.c
+  src/core/ext/filters/client_channel/resolver_registry.c
+  src/core/ext/filters/client_channel/retry_throttle.c
+  src/core/ext/filters/client_channel/subchannel.c
+  src/core/ext/filters/client_channel/subchannel_index.c
+  src/core/ext/filters/client_channel/uri_parser.c
+  src/core/ext/filters/deadline/deadline_filter.c
+  src/core/ext/transport/chttp2/transport/bin_decoder.c
+  src/core/ext/transport/chttp2/transport/bin_encoder.c
+  src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+  src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
+  src/core/ext/transport/chttp2/transport/frame_data.c
+  src/core/ext/transport/chttp2/transport/frame_goaway.c
+  src/core/ext/transport/chttp2/transport/frame_ping.c
+  src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+  src/core/ext/transport/chttp2/transport/frame_settings.c
+  src/core/ext/transport/chttp2/transport/frame_window_update.c
+  src/core/ext/transport/chttp2/transport/hpack_encoder.c
+  src/core/ext/transport/chttp2/transport/hpack_parser.c
+  src/core/ext/transport/chttp2/transport/hpack_table.c
+  src/core/ext/transport/chttp2/transport/http2_settings.c
+  src/core/ext/transport/chttp2/transport/huffsyms.c
+  src/core/ext/transport/chttp2/transport/incoming_metadata.c
+  src/core/ext/transport/chttp2/transport/parsing.c
+  src/core/ext/transport/chttp2/transport/stream_lists.c
+  src/core/ext/transport/chttp2/transport/stream_map.c
+  src/core/ext/transport/chttp2/transport/varint.c
+  src/core/ext/transport/chttp2/transport/writing.c
+  src/core/ext/transport/chttp2/alpn/alpn.c
+  src/core/ext/filters/http/client/http_client_filter.c
+  src/core/ext/filters/http/http_filters_plugin.c
+  src/core/ext/filters/http/message_compress/message_compress_filter.c
+  src/core/ext/filters/http/server/http_server_filter.c
 )
 
 if(WIN32 AND MSVC)
@@ -1763,17 +1815,6 @@
 )
 
 foreach(_hdr
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.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/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
@@ -1820,6 +1861,180 @@
   test/core/util/port_server_client.c
   test/core/util/slice_splitter.c
   test/core/util/trickle_endpoint.c
+  src/core/lib/channel/channel_args.c
+  src/core/lib/channel/channel_stack.c
+  src/core/lib/channel/channel_stack_builder.c
+  src/core/lib/channel/connected_channel.c
+  src/core/lib/channel/handshaker.c
+  src/core/lib/channel/handshaker_factory.c
+  src/core/lib/channel/handshaker_registry.c
+  src/core/lib/compression/compression.c
+  src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
+  src/core/lib/http/format_request.c
+  src/core/lib/http/httpcli.c
+  src/core/lib/http/parser.c
+  src/core/lib/iomgr/closure.c
+  src/core/lib/iomgr/combiner.c
+  src/core/lib/iomgr/endpoint.c
+  src/core/lib/iomgr/endpoint_pair_posix.c
+  src/core/lib/iomgr/endpoint_pair_uv.c
+  src/core/lib/iomgr/endpoint_pair_windows.c
+  src/core/lib/iomgr/error.c
+  src/core/lib/iomgr/ev_epoll1_linux.c
+  src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
+  src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
+  src/core/lib/iomgr/ev_epollex_linux.c
+  src/core/lib/iomgr/ev_epollsig_linux.c
+  src/core/lib/iomgr/ev_poll_posix.c
+  src/core/lib/iomgr/ev_posix.c
+  src/core/lib/iomgr/ev_windows.c
+  src/core/lib/iomgr/exec_ctx.c
+  src/core/lib/iomgr/executor.c
+  src/core/lib/iomgr/iocp_windows.c
+  src/core/lib/iomgr/iomgr.c
+  src/core/lib/iomgr/iomgr_posix.c
+  src/core/lib/iomgr/iomgr_uv.c
+  src/core/lib/iomgr/iomgr_windows.c
+  src/core/lib/iomgr/is_epollexclusive_available.c
+  src/core/lib/iomgr/load_file.c
+  src/core/lib/iomgr/lockfree_event.c
+  src/core/lib/iomgr/network_status_tracker.c
+  src/core/lib/iomgr/polling_entity.c
+  src/core/lib/iomgr/pollset_set_uv.c
+  src/core/lib/iomgr/pollset_set_windows.c
+  src/core/lib/iomgr/pollset_uv.c
+  src/core/lib/iomgr/pollset_windows.c
+  src/core/lib/iomgr/resolve_address_posix.c
+  src/core/lib/iomgr/resolve_address_uv.c
+  src/core/lib/iomgr/resolve_address_windows.c
+  src/core/lib/iomgr/resource_quota.c
+  src/core/lib/iomgr/sockaddr_utils.c
+  src/core/lib/iomgr/socket_factory_posix.c
+  src/core/lib/iomgr/socket_mutator.c
+  src/core/lib/iomgr/socket_utils_common_posix.c
+  src/core/lib/iomgr/socket_utils_linux.c
+  src/core/lib/iomgr/socket_utils_posix.c
+  src/core/lib/iomgr/socket_utils_uv.c
+  src/core/lib/iomgr/socket_utils_windows.c
+  src/core/lib/iomgr/socket_windows.c
+  src/core/lib/iomgr/tcp_client_posix.c
+  src/core/lib/iomgr/tcp_client_uv.c
+  src/core/lib/iomgr/tcp_client_windows.c
+  src/core/lib/iomgr/tcp_posix.c
+  src/core/lib/iomgr/tcp_server_posix.c
+  src/core/lib/iomgr/tcp_server_utils_posix_common.c
+  src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c
+  src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c
+  src/core/lib/iomgr/tcp_server_uv.c
+  src/core/lib/iomgr/tcp_server_windows.c
+  src/core/lib/iomgr/tcp_uv.c
+  src/core/lib/iomgr/tcp_windows.c
+  src/core/lib/iomgr/time_averaged_stats.c
+  src/core/lib/iomgr/timer_generic.c
+  src/core/lib/iomgr/timer_heap.c
+  src/core/lib/iomgr/timer_manager.c
+  src/core/lib/iomgr/timer_uv.c
+  src/core/lib/iomgr/udp_server.c
+  src/core/lib/iomgr/unix_sockets_posix.c
+  src/core/lib/iomgr/unix_sockets_posix_noop.c
+  src/core/lib/iomgr/wakeup_fd_cv.c
+  src/core/lib/iomgr/wakeup_fd_eventfd.c
+  src/core/lib/iomgr/wakeup_fd_nospecial.c
+  src/core/lib/iomgr/wakeup_fd_pipe.c
+  src/core/lib/iomgr/wakeup_fd_posix.c
+  src/core/lib/json/json.c
+  src/core/lib/json/json_reader.c
+  src/core/lib/json/json_string.c
+  src/core/lib/json/json_writer.c
+  src/core/lib/slice/b64.c
+  src/core/lib/slice/percent_encoding.c
+  src/core/lib/slice/slice.c
+  src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
+  src/core/lib/slice/slice_string_helpers.c
+  src/core/lib/surface/alarm.c
+  src/core/lib/surface/api_trace.c
+  src/core/lib/surface/byte_buffer.c
+  src/core/lib/surface/byte_buffer_reader.c
+  src/core/lib/surface/call.c
+  src/core/lib/surface/call_details.c
+  src/core/lib/surface/call_log_batch.c
+  src/core/lib/surface/channel.c
+  src/core/lib/surface/channel_init.c
+  src/core/lib/surface/channel_ping.c
+  src/core/lib/surface/channel_stack_type.c
+  src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
+  src/core/lib/surface/event_string.c
+  src/core/lib/surface/lame_client.cc
+  src/core/lib/surface/metadata_array.c
+  src/core/lib/surface/server.c
+  src/core/lib/surface/validate_metadata.c
+  src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
+  src/core/lib/transport/byte_stream.c
+  src/core/lib/transport/connectivity_state.c
+  src/core/lib/transport/error_utils.c
+  src/core/lib/transport/metadata.c
+  src/core/lib/transport/metadata_batch.c
+  src/core/lib/transport/pid_controller.c
+  src/core/lib/transport/service_config.c
+  src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
+  src/core/lib/transport/timeout_encoding.c
+  src/core/lib/transport/transport.c
+  src/core/lib/transport/transport_op_string.c
+  src/core/lib/debug/trace.c
+  src/core/ext/filters/client_channel/channel_connectivity.c
+  src/core/ext/filters/client_channel/client_channel.c
+  src/core/ext/filters/client_channel/client_channel_factory.c
+  src/core/ext/filters/client_channel/client_channel_plugin.c
+  src/core/ext/filters/client_channel/connector.c
+  src/core/ext/filters/client_channel/http_connect_handshaker.c
+  src/core/ext/filters/client_channel/http_proxy.c
+  src/core/ext/filters/client_channel/lb_policy.c
+  src/core/ext/filters/client_channel/lb_policy_factory.c
+  src/core/ext/filters/client_channel/lb_policy_registry.c
+  src/core/ext/filters/client_channel/parse_address.c
+  src/core/ext/filters/client_channel/proxy_mapper.c
+  src/core/ext/filters/client_channel/proxy_mapper_registry.c
+  src/core/ext/filters/client_channel/resolver.c
+  src/core/ext/filters/client_channel/resolver_factory.c
+  src/core/ext/filters/client_channel/resolver_registry.c
+  src/core/ext/filters/client_channel/retry_throttle.c
+  src/core/ext/filters/client_channel/subchannel.c
+  src/core/ext/filters/client_channel/subchannel_index.c
+  src/core/ext/filters/client_channel/uri_parser.c
+  src/core/ext/filters/deadline/deadline_filter.c
+  src/core/ext/transport/chttp2/transport/bin_decoder.c
+  src/core/ext/transport/chttp2/transport/bin_encoder.c
+  src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+  src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
+  src/core/ext/transport/chttp2/transport/frame_data.c
+  src/core/ext/transport/chttp2/transport/frame_goaway.c
+  src/core/ext/transport/chttp2/transport/frame_ping.c
+  src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+  src/core/ext/transport/chttp2/transport/frame_settings.c
+  src/core/ext/transport/chttp2/transport/frame_window_update.c
+  src/core/ext/transport/chttp2/transport/hpack_encoder.c
+  src/core/ext/transport/chttp2/transport/hpack_parser.c
+  src/core/ext/transport/chttp2/transport/hpack_table.c
+  src/core/ext/transport/chttp2/transport/http2_settings.c
+  src/core/ext/transport/chttp2/transport/huffsyms.c
+  src/core/ext/transport/chttp2/transport/incoming_metadata.c
+  src/core/ext/transport/chttp2/transport/parsing.c
+  src/core/ext/transport/chttp2/transport/stream_lists.c
+  src/core/ext/transport/chttp2/transport/stream_map.c
+  src/core/ext/transport/chttp2/transport/varint.c
+  src/core/ext/transport/chttp2/transport/writing.c
+  src/core/ext/transport/chttp2/alpn/alpn.c
+  src/core/ext/filters/http/client/http_client_filter.c
+  src/core/ext/filters/http/http_filters_plugin.c
+  src/core/ext/filters/http/message_compress/message_compress_filter.c
+  src/core/ext/filters/http/server/http_server_filter.c
 )
 
 if(WIN32 AND MSVC)
@@ -1854,9 +2069,35 @@
   gpr
   gpr_test_util
   grpc_unsecure
-  grpc
 )
 
+foreach(_hdr
+  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/exec_ctx_fwd.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/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_generic.h
+  include/grpc/impl/codegen/sync_posix.h
+  include/grpc/impl/codegen/sync_windows.h
+)
+  string(REPLACE "include/" "" _path ${_hdr})
+  get_filename_component(_path ${_path} PATH)
+  install(FILES ${_hdr}
+    DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
+  )
+endforeach()
 
 endif (gRPC_BUILD_TESTS)
 
@@ -1872,6 +2113,7 @@
   src/core/lib/channel/handshaker_registry.c
   src/core/lib/compression/compression.c
   src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
   src/core/lib/http/format_request.c
   src/core/lib/http/httpcli.c
   src/core/lib/http/parser.c
@@ -1994,6 +2236,7 @@
   src/core/ext/transport/chttp2/transport/bin_encoder.c
   src/core/ext/transport/chttp2/transport/chttp2_plugin.c
   src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
   src/core/ext/transport/chttp2/transport/frame_data.c
   src/core/ext/transport/chttp2/transport/frame_goaway.c
   src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -2041,6 +2284,8 @@
   src/core/ext/filters/client_channel/subchannel_index.c
   src/core/ext/filters/client_channel/uri_parser.c
   src/core/ext/filters/deadline/deadline_filter.c
+  src/core/ext/transport/inproc/inproc_plugin.c
+  src/core/ext/transport/inproc/inproc_transport.c
   src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
@@ -2119,17 +2364,6 @@
 )
 
 foreach(_hdr
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.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/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
@@ -2149,6 +2383,17 @@
   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/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/census.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
@@ -2297,9 +2542,6 @@
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
-  third_party/nanopb/pb_common.c
-  third_party/nanopb/pb_decode.c
-  third_party/nanopb/pb_encode.c
   src/cpp/codegen/codegen_init.cc
 )
 
@@ -2337,6 +2579,7 @@
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
+  gpr
 )
 
 foreach(_hdr
@@ -2385,6 +2628,62 @@
   include/grpc++/support/stub_options.h
   include/grpc++/support/sync_stream.h
   include/grpc++/support/time.h
+  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/avl.h
+  include/grpc/support/cmdline.h
+  include/grpc/support/cpu.h
+  include/grpc/support/histogram.h
+  include/grpc/support/host_port.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/subprocess.h
+  include/grpc/support/sync.h
+  include/grpc/support/sync_generic.h
+  include/grpc/support/sync_posix.h
+  include/grpc/support/sync_windows.h
+  include/grpc/support/thd.h
+  include/grpc/support/time.h
+  include/grpc/support/tls.h
+  include/grpc/support/tls_gcc.h
+  include/grpc/support/tls_msvc.h
+  include/grpc/support/tls_pthread.h
+  include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h
+  include/grpc/impl/codegen/compression_types.h
+  include/grpc/impl/codegen/connectivity_state.h
+  include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h
   include/grpc++/impl/codegen/async_unary_call.h
   include/grpc++/impl/codegen/call.h
@@ -2414,25 +2713,6 @@
   include/grpc++/impl/codegen/stub_options.h
   include/grpc++/impl/codegen/sync_stream.h
   include/grpc++/impl/codegen/time.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/exec_ctx_fwd.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/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_generic.h
-  include/grpc/impl/codegen/sync_posix.h
-  include/grpc/impl/codegen/sync_windows.h
   include/grpc++/impl/codegen/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
 )
@@ -2491,9 +2771,6 @@
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
-  third_party/nanopb/pb_common.c
-  third_party/nanopb/pb_decode.c
-  third_party/nanopb/pb_encode.c
   src/cpp/codegen/codegen_init.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.c
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
@@ -2502,6 +2779,7 @@
   src/core/ext/transport/chttp2/transport/bin_encoder.c
   src/core/ext/transport/chttp2/transport/chttp2_plugin.c
   src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/flow_control.c
   src/core/ext/transport/chttp2/transport/frame_data.c
   src/core/ext/transport/chttp2/transport/frame_goaway.c
   src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -2528,6 +2806,7 @@
   src/core/lib/channel/handshaker_registry.c
   src/core/lib/compression/compression.c
   src/core/lib/compression/message_compress.c
+  src/core/lib/compression/stream_compression.c
   src/core/lib/http/format_request.c
   src/core/lib/http/httpcli.c
   src/core/lib/http/parser.c
@@ -2688,6 +2967,9 @@
   src/core/ext/census/resource.c
   src/core/ext/census/trace_context.c
   src/core/ext/census/tracing.c
+  third_party/nanopb/pb_common.c
+  third_party/nanopb/pb_decode.c
+  third_party/nanopb/pb_encode.c
 )
 
 if(WIN32 AND MSVC)
@@ -2774,6 +3056,62 @@
   include/grpc++/support/stub_options.h
   include/grpc++/support/sync_stream.h
   include/grpc++/support/time.h
+  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/avl.h
+  include/grpc/support/cmdline.h
+  include/grpc/support/cpu.h
+  include/grpc/support/histogram.h
+  include/grpc/support/host_port.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/subprocess.h
+  include/grpc/support/sync.h
+  include/grpc/support/sync_generic.h
+  include/grpc/support/sync_posix.h
+  include/grpc/support/sync_windows.h
+  include/grpc/support/thd.h
+  include/grpc/support/time.h
+  include/grpc/support/tls.h
+  include/grpc/support/tls_gcc.h
+  include/grpc/support/tls_msvc.h
+  include/grpc/support/tls_pthread.h
+  include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h
+  include/grpc/impl/codegen/compression_types.h
+  include/grpc/impl/codegen/connectivity_state.h
+  include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h
   include/grpc++/impl/codegen/async_unary_call.h
   include/grpc++/impl/codegen/call.h
@@ -2803,36 +3141,6 @@
   include/grpc++/impl/codegen/stub_options.h
   include/grpc++/impl/codegen/sync_stream.h
   include/grpc++/impl/codegen/time.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/exec_ctx_fwd.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/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_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/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/census.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
@@ -3233,63 +3541,58 @@
 endforeach()
 
 endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
 
-add_library(grpc++_unsecure
-  src/cpp/client/insecure_credentials.cc
-  src/cpp/common/insecure_create_auth_context.cc
-  src/cpp/server/insecure_server_credentials.cc
-  src/cpp/client/channel_cc.cc
-  src/cpp/client/client_context.cc
-  src/cpp/client/create_channel.cc
-  src/cpp/client/create_channel_internal.cc
-  src/cpp/client/create_channel_posix.cc
-  src/cpp/client/credentials_cc.cc
-  src/cpp/client/generic_stub.cc
-  src/cpp/common/channel_arguments.cc
-  src/cpp/common/channel_filter.cc
-  src/cpp/common/completion_queue_cc.cc
-  src/cpp/common/core_codegen.cc
-  src/cpp/common/resource_quota_cc.cc
-  src/cpp/common/rpc_method.cc
-  src/cpp/common/version_cc.cc
-  src/cpp/server/async_generic_service.cc
-  src/cpp/server/channel_argument_option.cc
-  src/cpp/server/create_default_thread_pool.cc
-  src/cpp/server/dynamic_thread_pool.cc
-  src/cpp/server/health/default_health_check_service.cc
-  src/cpp/server/health/health.pb.c
-  src/cpp/server/health/health_check_service.cc
-  src/cpp/server/health/health_check_service_server_builder_option.cc
-  src/cpp/server/server_builder.cc
-  src/cpp/server/server_cc.cc
-  src/cpp/server/server_context.cc
-  src/cpp/server/server_credentials.cc
-  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
-  third_party/nanopb/pb_common.c
-  third_party/nanopb/pb_decode.c
-  third_party/nanopb/pb_encode.c
+add_library(grpc++_test_util_unsecure
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
+  ${_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
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_mock.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h
+  test/cpp/end2end/test_service_impl.cc
+  test/cpp/util/byte_buffer_proto_helper.cc
+  test/cpp/util/string_ref_helper.cc
+  test/cpp/util/subprocess.cc
   src/cpp/codegen/codegen_init.cc
 )
 
 if(WIN32 AND MSVC)
-  set_target_properties(grpc++_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_unsecure"
+  set_target_properties(grpc++_test_util_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_test_util_unsecure"
     COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
   )
   if (gRPC_INSTALL)
-    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_unsecure.pdb
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_util_unsecure.pdb
       DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL
     )
   endif()
 endif()
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/health/v1/health.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo_messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/duplicate/echo_duplicate.proto
+)
 
-target_include_directories(grpc++_unsecure
+target_include_directories(grpc++_test_util_unsecure
   PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
@@ -3302,64 +3605,22 @@
   PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  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(grpc++_unsecure
-  ${_gRPC_BASELIB_LIBRARIES}
+target_link_libraries(grpc++_test_util_unsecure
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  gpr
+  grpc++_unsecure
+  grpc_test_util_unsecure
   grpc_unsecure
-  grpc
 )
 
 foreach(_hdr
-  include/grpc++/alarm.h
-  include/grpc++/channel.h
-  include/grpc++/client_context.h
-  include/grpc++/completion_queue.h
-  include/grpc++/create_channel.h
-  include/grpc++/create_channel_posix.h
-  include/grpc++/ext/health_check_service_server_builder_option.h
-  include/grpc++/generic/async_generic_service.h
-  include/grpc++/generic/generic_stub.h
-  include/grpc++/grpc++.h
-  include/grpc++/health_check_service_interface.h
-  include/grpc++/impl/call.h
-  include/grpc++/impl/channel_argument_option.h
-  include/grpc++/impl/client_unary_call.h
-  include/grpc++/impl/codegen/core_codegen.h
-  include/grpc++/impl/grpc_library.h
-  include/grpc++/impl/method_handler_impl.h
-  include/grpc++/impl/rpc_method.h
-  include/grpc++/impl/rpc_service_method.h
-  include/grpc++/impl/serialization_traits.h
-  include/grpc++/impl/server_builder_option.h
-  include/grpc++/impl/server_builder_plugin.h
-  include/grpc++/impl/server_initializer.h
-  include/grpc++/impl/service_type.h
-  include/grpc++/resource_quota.h
-  include/grpc++/security/auth_context.h
-  include/grpc++/security/auth_metadata_processor.h
-  include/grpc++/security/credentials.h
-  include/grpc++/security/server_credentials.h
-  include/grpc++/server.h
-  include/grpc++/server_builder.h
-  include/grpc++/server_context.h
-  include/grpc++/server_posix.h
-  include/grpc++/support/async_stream.h
-  include/grpc++/support/async_unary_call.h
-  include/grpc++/support/byte_buffer.h
-  include/grpc++/support/channel_arguments.h
-  include/grpc++/support/config.h
-  include/grpc++/support/slice.h
-  include/grpc++/support/status.h
-  include/grpc++/support/status_code_enum.h
-  include/grpc++/support/string_ref.h
-  include/grpc++/support/stub_options.h
-  include/grpc++/support/sync_stream.h
-  include/grpc++/support/time.h
   include/grpc++/impl/codegen/async_stream.h
   include/grpc++/impl/codegen/async_unary_call.h
   include/grpc++/impl/codegen/call.h
@@ -3408,6 +3669,225 @@
   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/proto_utils.h
+  include/grpc++/impl/codegen/config_protobuf.h
+)
+  string(REPLACE "include/" "" _path ${_hdr})
+  get_filename_component(_path ${_path} PATH)
+  install(FILES ${_hdr}
+    DESTINATION "${gRPC_INSTALL_INCLUDEDIR}/${_path}"
+  )
+endforeach()
+
+endif (gRPC_BUILD_TESTS)
+
+add_library(grpc++_unsecure
+  src/cpp/client/insecure_credentials.cc
+  src/cpp/common/insecure_create_auth_context.cc
+  src/cpp/server/insecure_server_credentials.cc
+  src/cpp/client/channel_cc.cc
+  src/cpp/client/client_context.cc
+  src/cpp/client/create_channel.cc
+  src/cpp/client/create_channel_internal.cc
+  src/cpp/client/create_channel_posix.cc
+  src/cpp/client/credentials_cc.cc
+  src/cpp/client/generic_stub.cc
+  src/cpp/common/channel_arguments.cc
+  src/cpp/common/channel_filter.cc
+  src/cpp/common/completion_queue_cc.cc
+  src/cpp/common/core_codegen.cc
+  src/cpp/common/resource_quota_cc.cc
+  src/cpp/common/rpc_method.cc
+  src/cpp/common/version_cc.cc
+  src/cpp/server/async_generic_service.cc
+  src/cpp/server/channel_argument_option.cc
+  src/cpp/server/create_default_thread_pool.cc
+  src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health.pb.c
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
+  src/cpp/server/server_builder.cc
+  src/cpp/server/server_cc.cc
+  src/cpp/server/server_context.cc
+  src/cpp/server/server_credentials.cc
+  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
+)
+
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_unsecure"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_unsecure.pdb
+      DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
+
+target_include_directories(grpc++_unsecure
+  PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(grpc++_unsecure
+  ${_gRPC_BASELIB_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  gpr
+  grpc_unsecure
+)
+
+foreach(_hdr
+  include/grpc++/alarm.h
+  include/grpc++/channel.h
+  include/grpc++/client_context.h
+  include/grpc++/completion_queue.h
+  include/grpc++/create_channel.h
+  include/grpc++/create_channel_posix.h
+  include/grpc++/ext/health_check_service_server_builder_option.h
+  include/grpc++/generic/async_generic_service.h
+  include/grpc++/generic/generic_stub.h
+  include/grpc++/grpc++.h
+  include/grpc++/health_check_service_interface.h
+  include/grpc++/impl/call.h
+  include/grpc++/impl/channel_argument_option.h
+  include/grpc++/impl/client_unary_call.h
+  include/grpc++/impl/codegen/core_codegen.h
+  include/grpc++/impl/grpc_library.h
+  include/grpc++/impl/method_handler_impl.h
+  include/grpc++/impl/rpc_method.h
+  include/grpc++/impl/rpc_service_method.h
+  include/grpc++/impl/serialization_traits.h
+  include/grpc++/impl/server_builder_option.h
+  include/grpc++/impl/server_builder_plugin.h
+  include/grpc++/impl/server_initializer.h
+  include/grpc++/impl/service_type.h
+  include/grpc++/resource_quota.h
+  include/grpc++/security/auth_context.h
+  include/grpc++/security/auth_metadata_processor.h
+  include/grpc++/security/credentials.h
+  include/grpc++/security/server_credentials.h
+  include/grpc++/server.h
+  include/grpc++/server_builder.h
+  include/grpc++/server_context.h
+  include/grpc++/server_posix.h
+  include/grpc++/support/async_stream.h
+  include/grpc++/support/async_unary_call.h
+  include/grpc++/support/byte_buffer.h
+  include/grpc++/support/channel_arguments.h
+  include/grpc++/support/config.h
+  include/grpc++/support/slice.h
+  include/grpc++/support/status.h
+  include/grpc++/support/status_code_enum.h
+  include/grpc++/support/string_ref.h
+  include/grpc++/support/stub_options.h
+  include/grpc++/support/sync_stream.h
+  include/grpc++/support/time.h
+  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/avl.h
+  include/grpc/support/cmdline.h
+  include/grpc/support/cpu.h
+  include/grpc/support/histogram.h
+  include/grpc/support/host_port.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/subprocess.h
+  include/grpc/support/sync.h
+  include/grpc/support/sync_generic.h
+  include/grpc/support/sync_posix.h
+  include/grpc/support/sync_windows.h
+  include/grpc/support/thd.h
+  include/grpc/support/time.h
+  include/grpc/support/tls.h
+  include/grpc/support/tls_gcc.h
+  include/grpc/support/tls_msvc.h
+  include/grpc/support/tls_pthread.h
+  include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h
+  include/grpc/impl/codegen/compression_types.h
+  include/grpc/impl/codegen/connectivity_state.h
+  include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h
+  include/grpc++/impl/codegen/async_unary_call.h
+  include/grpc++/impl/codegen/call.h
+  include/grpc++/impl/codegen/call_hook.h
+  include/grpc++/impl/codegen/channel_interface.h
+  include/grpc++/impl/codegen/client_context.h
+  include/grpc++/impl/codegen/client_unary_call.h
+  include/grpc++/impl/codegen/completion_queue.h
+  include/grpc++/impl/codegen/completion_queue_tag.h
+  include/grpc++/impl/codegen/config.h
+  include/grpc++/impl/codegen/core_codegen_interface.h
+  include/grpc++/impl/codegen/create_auth_context.h
+  include/grpc++/impl/codegen/grpc_library.h
+  include/grpc++/impl/codegen/metadata_map.h
+  include/grpc++/impl/codegen/method_handler_impl.h
+  include/grpc++/impl/codegen/rpc_method.h
+  include/grpc++/impl/codegen/rpc_service_method.h
+  include/grpc++/impl/codegen/security/auth_context.h
+  include/grpc++/impl/codegen/serialization_traits.h
+  include/grpc++/impl/codegen/server_context.h
+  include/grpc++/impl/codegen/server_interface.h
+  include/grpc++/impl/codegen/service_type.h
+  include/grpc++/impl/codegen/slice.h
+  include/grpc++/impl/codegen/status.h
+  include/grpc++/impl/codegen/status_code_enum.h
+  include/grpc++/impl/codegen/string_ref.h
+  include/grpc++/impl/codegen/stub_options.h
+  include/grpc++/impl/codegen/sync_stream.h
+  include/grpc++/impl/codegen/time.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
@@ -3467,9 +3947,9 @@
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   benchmark
-  grpc++
-  grpc_test_util
-  grpc
+  grpc++_unsecure
+  grpc_test_util_unsecure
+  grpc_unsecure
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -4339,6 +4819,7 @@
   test/core/end2end/tests/payload.c
   test/core/end2end/tests/ping.c
   test/core/end2end/tests/ping_pong_streaming.c
+  test/core/end2end/tests/proxy_auth.c
   test/core/end2end/tests/registered_call.c
   test/core/end2end/tests/request_with_flags.c
   test/core/end2end/tests/request_with_payload.c
@@ -4438,6 +4919,7 @@
   test/core/end2end/tests/payload.c
   test/core/end2end/tests/ping.c
   test/core/end2end/tests/ping_pong_streaming.c
+  test/core/end2end/tests/proxy_auth.c
   test/core/end2end/tests/registered_call.c
   test/core/end2end/tests/request_with_flags.c
   test/core/end2end/tests/request_with_payload.c
@@ -4768,6 +5250,37 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(byte_stream_test
+  test/core/transport/byte_stream_test.c
+)
+
+
+target_include_directories(byte_stream_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(byte_stream_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(census_context_test
   test/core/census/context_test.c
 )
@@ -8175,6 +8688,37 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(stream_compression_test
+  test/core/compression/stream_compression_test.c
+)
+
+
+target_include_directories(stream_compression_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(stream_compression_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(stream_owned_slice_test
   test/core/transport/stream_owned_slice_test.c
 )
@@ -8744,10 +9288,10 @@
 target_link_libraries(alarm_cpp_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -8873,10 +9417,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -8919,10 +9463,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -8965,10 +9509,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9011,10 +9555,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9057,10 +9601,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9103,10 +9647,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9149,10 +9693,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9195,10 +9739,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9241,10 +9785,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9287,10 +9831,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9333,10 +9877,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9379,10 +9923,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9425,10 +9969,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -9471,10 +10015,10 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -11405,6 +11949,7 @@
   grpc
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -11756,6 +12301,7 @@
   grpc
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -11849,11 +12395,11 @@
 target_link_libraries(server_builder_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
-  grpc_test_util
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
   gpr_test_util
-  grpc++
-  grpc
+  grpc++_unsecure
+  grpc_unsecure
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
 )
@@ -11988,6 +12534,62 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(server_request_call_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_request_call_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_request_call_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  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_request_call_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 (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(shutdown_test
   test/cpp/end2end/shutdown_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -12219,8 +12821,8 @@
 target_link_libraries(thread_manager_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++
-  grpc
+  grpc++_unsecure
+  grpc_unsecure
   gpr
   grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -12259,10 +12861,10 @@
 target_link_libraries(thread_stress_test
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc++_test_util
-  grpc_test_util
-  grpc++
-  grpc
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  grpc++_unsecure
+  grpc_unsecure
   gpr_test_util
   gpr
   ${_gRPC_GFLAGS_LIBRARIES}
@@ -13355,6 +13957,38 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(inproc_test
+  test/core/end2end/fixtures/inproc.c
+)
+
+
+target_include_directories(inproc_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(inproc_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  end2end_tests
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(h2_census_nosec_test
   test/core/end2end/fixtures/h2_census.c
 )
@@ -13809,6 +14443,38 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(inproc_nosec_test
+  test/core/end2end/fixtures/inproc.c
+)
+
+
+target_include_directories(inproc_nosec_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(inproc_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  end2end_nosec_tests
+  grpc_test_util_unsecure
+  grpc_unsecure
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(api_fuzzer_one_entry
   test/core/end2end/fuzzers/api_fuzzer.c
   test/core/util/one_corpus_entry_fuzzer.c
diff --git a/Makefile b/Makefile
index 23f8706..5168b30 100644
--- a/Makefile
+++ b/Makefile
@@ -954,6 +954,7 @@
 bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
 bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
+byte_stream_test: $(BINDIR)/$(CONFIG)/byte_stream_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
 census_intrusive_hash_map_test: $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test
 census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
@@ -1075,6 +1076,7 @@
 socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
 ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
 status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
+stream_compression_test: $(BINDIR)/$(CONFIG)/stream_compression_test
 stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test
 tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test
 tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test
@@ -1166,6 +1168,7 @@
 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
+server_request_call_test: $(BINDIR)/$(CONFIG)/server_request_call_test
 shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test
 status_test: $(BINDIR)/$(CONFIG)/status_test
 streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
@@ -1243,6 +1246,7 @@
 h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_test
 h2_ssl_proxy_test: $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test
 h2_uds_test: $(BINDIR)/$(CONFIG)/h2_uds_test
+inproc_test: $(BINDIR)/$(CONFIG)/inproc_test
 h2_census_nosec_test: $(BINDIR)/$(CONFIG)/h2_census_nosec_test
 h2_compress_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_nosec_test
 h2_fd_nosec_test: $(BINDIR)/$(CONFIG)/h2_fd_nosec_test
@@ -1257,6 +1261,7 @@
 h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test
 h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test
 h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test
+inproc_nosec_test: $(BINDIR)/$(CONFIG)/inproc_nosec_test
 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
@@ -1323,9 +1328,9 @@
 pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
 
 ifeq ($(EMBED_OPENSSL),true)
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.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_aes_test_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_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_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_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_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_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_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_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_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(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_aes_test_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_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_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_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_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_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_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_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_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 else
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.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++_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
 endif
 
 
@@ -1341,6 +1346,7 @@
   $(BINDIR)/$(CONFIG)/bdp_estimator_test \
   $(BINDIR)/$(CONFIG)/bin_decoder_test \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
+  $(BINDIR)/$(CONFIG)/byte_stream_test \
   $(BINDIR)/$(CONFIG)/census_context_test \
   $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test \
   $(BINDIR)/$(CONFIG)/census_resource_test \
@@ -1443,6 +1449,7 @@
   $(BINDIR)/$(CONFIG)/sockaddr_utils_test \
   $(BINDIR)/$(CONFIG)/socket_utils_test \
   $(BINDIR)/$(CONFIG)/status_conversion_test \
+  $(BINDIR)/$(CONFIG)/stream_compression_test \
   $(BINDIR)/$(CONFIG)/stream_owned_slice_test \
   $(BINDIR)/$(CONFIG)/tcp_client_posix_test \
   $(BINDIR)/$(CONFIG)/tcp_client_uv_test \
@@ -1492,6 +1499,7 @@
   $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test \
   $(BINDIR)/$(CONFIG)/h2_uds_test \
+  $(BINDIR)/$(CONFIG)/inproc_test \
   $(BINDIR)/$(CONFIG)/h2_census_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_compress_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_fd_nosec_test \
@@ -1506,6 +1514,7 @@
   $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_uds_nosec_test \
+  $(BINDIR)/$(CONFIG)/inproc_nosec_test \
   $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
@@ -1589,6 +1598,7 @@
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_crash_test \
   $(BINDIR)/$(CONFIG)/server_crash_test_client \
+  $(BINDIR)/$(CONFIG)/server_request_call_test \
   $(BINDIR)/$(CONFIG)/shutdown_test \
   $(BINDIR)/$(CONFIG)/status_test \
   $(BINDIR)/$(CONFIG)/streaming_throughput_test \
@@ -1703,6 +1713,7 @@
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_crash_test \
   $(BINDIR)/$(CONFIG)/server_crash_test_client \
+  $(BINDIR)/$(CONFIG)/server_request_call_test \
   $(BINDIR)/$(CONFIG)/shutdown_test \
   $(BINDIR)/$(CONFIG)/status_test \
   $(BINDIR)/$(CONFIG)/streaming_throughput_test \
@@ -1737,6 +1748,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 )
 	$(E) "[RUN]     Testing bin_encoder_test"
 	$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
+	$(E) "[RUN]     Testing byte_stream_test"
+	$(Q) $(BINDIR)/$(CONFIG)/byte_stream_test || ( echo test byte_stream_test failed ; exit 1 )
 	$(E) "[RUN]     Testing census_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing census_intrusive_hash_map_test"
@@ -1925,6 +1938,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
 	$(E) "[RUN]     Testing status_conversion_test"
 	$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
+	$(E) "[RUN]     Testing stream_compression_test"
+	$(Q) $(BINDIR)/$(CONFIG)/stream_compression_test || ( echo test stream_compression_test failed ; exit 1 )
 	$(E) "[RUN]     Testing stream_owned_slice_test"
 	$(Q) $(BINDIR)/$(CONFIG)/stream_owned_slice_test || ( echo test stream_owned_slice_test failed ; exit 1 )
 	$(E) "[RUN]     Testing tcp_client_posix_test"
@@ -2095,6 +2110,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/server_context_test_spouse_test || ( echo test server_context_test_spouse_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_crash_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_crash_test || ( echo test server_crash_test failed ; exit 1 )
+	$(E) "[RUN]     Testing server_request_call_test"
+	$(Q) $(BINDIR)/$(CONFIG)/server_request_call_test || ( echo test server_request_call_test failed ; exit 1 )
 	$(E) "[RUN]     Testing shutdown_test"
 	$(Q) $(BINDIR)/$(CONFIG)/shutdown_test || ( echo test shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing status_test"
@@ -2233,7 +2250,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: src/proto/grpc/health/v1/health.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: src/proto/grpc/health/v1/health.proto $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2249,7 +2266,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2265,7 +2282,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2281,7 +2298,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc: src/proto/grpc/status/status.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc: src/proto/grpc/status/status.proto $(GENDIR)/src/proto/grpc/status/status.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2298,7 +2315,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=generate_mock_code=true:$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
@@ -2314,7 +2331,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(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.grpc.pb.cc: src/proto/grpc/testing/control.proto $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(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
 	$(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) $<
@@ -2330,7 +2347,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+$(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_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) $<
@@ -2347,7 +2364,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(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.grpc.pb.cc: src/proto/grpc/testing/echo.proto $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_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=generate_mock_code=true:$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
@@ -2363,7 +2380,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2379,7 +2396,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2395,7 +2412,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2411,7 +2428,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2427,7 +2444,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2443,7 +2460,7 @@
 	$(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 $(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/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(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/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.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) $<
@@ -2459,7 +2476,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+$(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
 	$(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) $<
@@ -2475,7 +2492,7 @@
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.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/test.grpc.pb.cc: src/proto/grpc/testing/test.proto $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(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) $<
@@ -2887,6 +2904,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -3008,6 +3026,7 @@
     src/core/ext/transport/chttp2/transport/bin_encoder.c \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
     src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
     src/core/ext/transport/chttp2/transport/frame_data.c \
     src/core/ext/transport/chttp2/transport/frame_goaway.c \
     src/core/ext/transport/chttp2/transport/frame_ping.c \
@@ -3055,6 +3074,7 @@
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/tsi/fake_transport_security.c \
+    src/core/tsi/gts_transport_security.c \
     src/core/tsi/ssl_transport_security.c \
     src/core/tsi/transport_security.c \
     src/core/tsi/transport_security_adapter.c \
@@ -3086,6 +3106,8 @@
     src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
+    src/core/ext/transport/inproc/inproc_plugin.c \
+    src/core/ext/transport/inproc/inproc_transport.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \
@@ -3128,17 +3150,6 @@
     src/core/plugin_registry/grpc_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.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/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
@@ -3159,6 +3170,17 @@
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
     include/grpc/grpc_security.h \
+    include/grpc/byte_buffer.h \
+    include/grpc/byte_buffer_reader.h \
+    include/grpc/compression.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/census.h \
 
 LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC))))
@@ -3224,6 +3246,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -3348,6 +3371,7 @@
     src/core/ext/transport/chttp2/transport/bin_encoder.c \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
     src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
     src/core/ext/transport/chttp2/transport/frame_data.c \
     src/core/ext/transport/chttp2/transport/frame_goaway.c \
     src/core/ext/transport/chttp2/transport/frame_ping.c \
@@ -3416,6 +3440,7 @@
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/tsi/fake_transport_security.c \
+    src/core/tsi/gts_transport_security.c \
     src/core/tsi/ssl_transport_security.c \
     src/core/tsi/transport_security.c \
     src/core/tsi/transport_security_adapter.c \
@@ -3425,17 +3450,6 @@
     src/core/plugin_registry/grpc_cronet_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.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/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
@@ -3457,6 +3471,7 @@
     include/grpc/impl/codegen/sync_windows.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))))
 
@@ -3540,6 +3555,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -3656,19 +3672,56 @@
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
     src/core/lib/debug/trace.c \
+    src/core/ext/filters/client_channel/channel_connectivity.c \
+    src/core/ext/filters/client_channel/client_channel.c \
+    src/core/ext/filters/client_channel/client_channel_factory.c \
+    src/core/ext/filters/client_channel/client_channel_plugin.c \
+    src/core/ext/filters/client_channel/connector.c \
+    src/core/ext/filters/client_channel/http_connect_handshaker.c \
+    src/core/ext/filters/client_channel/http_proxy.c \
+    src/core/ext/filters/client_channel/lb_policy.c \
+    src/core/ext/filters/client_channel/lb_policy_factory.c \
+    src/core/ext/filters/client_channel/lb_policy_registry.c \
+    src/core/ext/filters/client_channel/parse_address.c \
+    src/core/ext/filters/client_channel/proxy_mapper.c \
+    src/core/ext/filters/client_channel/proxy_mapper_registry.c \
+    src/core/ext/filters/client_channel/resolver.c \
+    src/core/ext/filters/client_channel/resolver_factory.c \
+    src/core/ext/filters/client_channel/resolver_registry.c \
+    src/core/ext/filters/client_channel/retry_throttle.c \
+    src/core/ext/filters/client_channel/subchannel.c \
+    src/core/ext/filters/client_channel/subchannel_index.c \
+    src/core/ext/filters/client_channel/uri_parser.c \
+    src/core/ext/filters/deadline/deadline_filter.c \
+    src/core/ext/transport/chttp2/transport/bin_decoder.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/http2_settings.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
+    src/core/ext/transport/chttp2/alpn/alpn.c \
+    src/core/ext/filters/http/client/http_client_filter.c \
+    src/core/ext/filters/http/http_filters_plugin.c \
+    src/core/ext/filters/http/message_compress/message_compress_filter.c \
+    src/core/ext/filters/http/server/http_server_filter.c \
 
 PUBLIC_HEADERS_C += \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.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/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
@@ -3739,8 +3792,201 @@
     test/core/util/port_server_client.c \
     test/core/util/slice_splitter.c \
     test/core/util/trickle_endpoint.c \
+    src/core/lib/channel/channel_args.c \
+    src/core/lib/channel/channel_stack.c \
+    src/core/lib/channel/channel_stack_builder.c \
+    src/core/lib/channel/connected_channel.c \
+    src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
+    src/core/lib/compression/compression.c \
+    src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
+    src/core/lib/http/format_request.c \
+    src/core/lib/http/httpcli.c \
+    src/core/lib/http/parser.c \
+    src/core/lib/iomgr/closure.c \
+    src/core/lib/iomgr/combiner.c \
+    src/core/lib/iomgr/endpoint.c \
+    src/core/lib/iomgr/endpoint_pair_posix.c \
+    src/core/lib/iomgr/endpoint_pair_uv.c \
+    src/core/lib/iomgr/endpoint_pair_windows.c \
+    src/core/lib/iomgr/error.c \
+    src/core/lib/iomgr/ev_epoll1_linux.c \
+    src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
+    src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
+    src/core/lib/iomgr/ev_epollex_linux.c \
+    src/core/lib/iomgr/ev_epollsig_linux.c \
+    src/core/lib/iomgr/ev_poll_posix.c \
+    src/core/lib/iomgr/ev_posix.c \
+    src/core/lib/iomgr/ev_windows.c \
+    src/core/lib/iomgr/exec_ctx.c \
+    src/core/lib/iomgr/executor.c \
+    src/core/lib/iomgr/iocp_windows.c \
+    src/core/lib/iomgr/iomgr.c \
+    src/core/lib/iomgr/iomgr_posix.c \
+    src/core/lib/iomgr/iomgr_uv.c \
+    src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/is_epollexclusive_available.c \
+    src/core/lib/iomgr/load_file.c \
+    src/core/lib/iomgr/lockfree_event.c \
+    src/core/lib/iomgr/network_status_tracker.c \
+    src/core/lib/iomgr/polling_entity.c \
+    src/core/lib/iomgr/pollset_set_uv.c \
+    src/core/lib/iomgr/pollset_set_windows.c \
+    src/core/lib/iomgr/pollset_uv.c \
+    src/core/lib/iomgr/pollset_windows.c \
+    src/core/lib/iomgr/resolve_address_posix.c \
+    src/core/lib/iomgr/resolve_address_uv.c \
+    src/core/lib/iomgr/resolve_address_windows.c \
+    src/core/lib/iomgr/resource_quota.c \
+    src/core/lib/iomgr/sockaddr_utils.c \
+    src/core/lib/iomgr/socket_factory_posix.c \
+    src/core/lib/iomgr/socket_mutator.c \
+    src/core/lib/iomgr/socket_utils_common_posix.c \
+    src/core/lib/iomgr/socket_utils_linux.c \
+    src/core/lib/iomgr/socket_utils_posix.c \
+    src/core/lib/iomgr/socket_utils_uv.c \
+    src/core/lib/iomgr/socket_utils_windows.c \
+    src/core/lib/iomgr/socket_windows.c \
+    src/core/lib/iomgr/tcp_client_posix.c \
+    src/core/lib/iomgr/tcp_client_uv.c \
+    src/core/lib/iomgr/tcp_client_windows.c \
+    src/core/lib/iomgr/tcp_posix.c \
+    src/core/lib/iomgr/tcp_server_posix.c \
+    src/core/lib/iomgr/tcp_server_utils_posix_common.c \
+    src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \
+    src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \
+    src/core/lib/iomgr/tcp_server_uv.c \
+    src/core/lib/iomgr/tcp_server_windows.c \
+    src/core/lib/iomgr/tcp_uv.c \
+    src/core/lib/iomgr/tcp_windows.c \
+    src/core/lib/iomgr/time_averaged_stats.c \
+    src/core/lib/iomgr/timer_generic.c \
+    src/core/lib/iomgr/timer_heap.c \
+    src/core/lib/iomgr/timer_manager.c \
+    src/core/lib/iomgr/timer_uv.c \
+    src/core/lib/iomgr/udp_server.c \
+    src/core/lib/iomgr/unix_sockets_posix.c \
+    src/core/lib/iomgr/unix_sockets_posix_noop.c \
+    src/core/lib/iomgr/wakeup_fd_cv.c \
+    src/core/lib/iomgr/wakeup_fd_eventfd.c \
+    src/core/lib/iomgr/wakeup_fd_nospecial.c \
+    src/core/lib/iomgr/wakeup_fd_pipe.c \
+    src/core/lib/iomgr/wakeup_fd_posix.c \
+    src/core/lib/json/json.c \
+    src/core/lib/json/json_reader.c \
+    src/core/lib/json/json_string.c \
+    src/core/lib/json/json_writer.c \
+    src/core/lib/slice/b64.c \
+    src/core/lib/slice/percent_encoding.c \
+    src/core/lib/slice/slice.c \
+    src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
+    src/core/lib/slice/slice_string_helpers.c \
+    src/core/lib/surface/alarm.c \
+    src/core/lib/surface/api_trace.c \
+    src/core/lib/surface/byte_buffer.c \
+    src/core/lib/surface/byte_buffer_reader.c \
+    src/core/lib/surface/call.c \
+    src/core/lib/surface/call_details.c \
+    src/core/lib/surface/call_log_batch.c \
+    src/core/lib/surface/channel.c \
+    src/core/lib/surface/channel_init.c \
+    src/core/lib/surface/channel_ping.c \
+    src/core/lib/surface/channel_stack_type.c \
+    src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
+    src/core/lib/surface/event_string.c \
+    src/core/lib/surface/lame_client.cc \
+    src/core/lib/surface/metadata_array.c \
+    src/core/lib/surface/server.c \
+    src/core/lib/surface/validate_metadata.c \
+    src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
+    src/core/lib/transport/byte_stream.c \
+    src/core/lib/transport/connectivity_state.c \
+    src/core/lib/transport/error_utils.c \
+    src/core/lib/transport/metadata.c \
+    src/core/lib/transport/metadata_batch.c \
+    src/core/lib/transport/pid_controller.c \
+    src/core/lib/transport/service_config.c \
+    src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
+    src/core/lib/transport/timeout_encoding.c \
+    src/core/lib/transport/transport.c \
+    src/core/lib/transport/transport_op_string.c \
+    src/core/lib/debug/trace.c \
+    src/core/ext/filters/client_channel/channel_connectivity.c \
+    src/core/ext/filters/client_channel/client_channel.c \
+    src/core/ext/filters/client_channel/client_channel_factory.c \
+    src/core/ext/filters/client_channel/client_channel_plugin.c \
+    src/core/ext/filters/client_channel/connector.c \
+    src/core/ext/filters/client_channel/http_connect_handshaker.c \
+    src/core/ext/filters/client_channel/http_proxy.c \
+    src/core/ext/filters/client_channel/lb_policy.c \
+    src/core/ext/filters/client_channel/lb_policy_factory.c \
+    src/core/ext/filters/client_channel/lb_policy_registry.c \
+    src/core/ext/filters/client_channel/parse_address.c \
+    src/core/ext/filters/client_channel/proxy_mapper.c \
+    src/core/ext/filters/client_channel/proxy_mapper_registry.c \
+    src/core/ext/filters/client_channel/resolver.c \
+    src/core/ext/filters/client_channel/resolver_factory.c \
+    src/core/ext/filters/client_channel/resolver_registry.c \
+    src/core/ext/filters/client_channel/retry_throttle.c \
+    src/core/ext/filters/client_channel/subchannel.c \
+    src/core/ext/filters/client_channel/subchannel_index.c \
+    src/core/ext/filters/client_channel/uri_parser.c \
+    src/core/ext/filters/deadline/deadline_filter.c \
+    src/core/ext/transport/chttp2/transport/bin_decoder.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/http2_settings.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
+    src/core/ext/transport/chttp2/alpn/alpn.c \
+    src/core/ext/filters/http/client/http_client_filter.c \
+    src/core/ext/filters/http/http_filters_plugin.c \
+    src/core/ext/filters/http/message_compress/message_compress_filter.c \
+    src/core/ext/filters/http/server/http_server_filter.c \
 
 PUBLIC_HEADERS_C += \
+    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/exec_ctx_fwd.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/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_generic.h \
+    include/grpc/impl/codegen/sync_posix.h \
+    include/grpc/impl/codegen/sync_windows.h \
 
 LIBGRPC_TEST_UTIL_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_TEST_UTIL_UNSECURE_SRC))))
 
@@ -3774,6 +4020,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -3896,6 +4143,7 @@
     src/core/ext/transport/chttp2/transport/bin_encoder.c \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
     src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
     src/core/ext/transport/chttp2/transport/frame_data.c \
     src/core/ext/transport/chttp2/transport/frame_goaway.c \
     src/core/ext/transport/chttp2/transport/frame_ping.c \
@@ -3943,6 +4191,8 @@
     src/core/ext/filters/client_channel/subchannel_index.c \
     src/core/ext/filters/client_channel/uri_parser.c \
     src/core/ext/filters/deadline/deadline_filter.c \
+    src/core/ext/transport/inproc/inproc_plugin.c \
+    src/core/ext/transport/inproc/inproc_transport.c \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c \
@@ -3985,17 +4235,6 @@
     src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.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/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
@@ -4015,6 +4254,17 @@
     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/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/census.h \
 
 LIBGRPC_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_UNSECURE_SRC))))
@@ -4174,9 +4424,6 @@
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
-    third_party/nanopb/pb_common.c \
-    third_party/nanopb/pb_decode.c \
-    third_party/nanopb/pb_encode.c \
     src/cpp/codegen/codegen_init.cc \
 
 PUBLIC_HEADERS_CXX += \
@@ -4225,6 +4472,62 @@
     include/grpc++/support/stub_options.h \
     include/grpc++/support/sync_stream.h \
     include/grpc++/support/time.h \
+    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/avl.h \
+    include/grpc/support/cmdline.h \
+    include/grpc/support/cpu.h \
+    include/grpc/support/histogram.h \
+    include/grpc/support/host_port.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/subprocess.h \
+    include/grpc/support/sync.h \
+    include/grpc/support/sync_generic.h \
+    include/grpc/support/sync_posix.h \
+    include/grpc/support/sync_windows.h \
+    include/grpc/support/thd.h \
+    include/grpc/support/time.h \
+    include/grpc/support/tls.h \
+    include/grpc/support/tls_gcc.h \
+    include/grpc/support/tls_msvc.h \
+    include/grpc/support/tls_pthread.h \
+    include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h \
+    include/grpc/impl/codegen/compression_types.h \
+    include/grpc/impl/codegen/connectivity_state.h \
+    include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h \
     include/grpc++/impl/codegen/async_unary_call.h \
     include/grpc++/impl/codegen/call.h \
@@ -4254,25 +4557,6 @@
     include/grpc++/impl/codegen/stub_options.h \
     include/grpc++/impl/codegen/sync_stream.h \
     include/grpc++/impl/codegen/time.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/exec_ctx_fwd.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/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_generic.h \
-    include/grpc/impl/codegen/sync_posix.h \
-    include/grpc/impl/codegen/sync_windows.h \
     include/grpc++/impl/codegen/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
 
@@ -4311,18 +4595,18 @@
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll -lgpr$(SHARED_VERSION_CORE)-dll
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
 endif
@@ -4377,9 +4661,6 @@
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
-    third_party/nanopb/pb_common.c \
-    third_party/nanopb/pb_decode.c \
-    third_party/nanopb/pb_encode.c \
     src/cpp/codegen/codegen_init.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
@@ -4388,6 +4669,7 @@
     src/core/ext/transport/chttp2/transport/bin_encoder.c \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
     src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
     src/core/ext/transport/chttp2/transport/frame_data.c \
     src/core/ext/transport/chttp2/transport/frame_goaway.c \
     src/core/ext/transport/chttp2/transport/frame_ping.c \
@@ -4414,6 +4696,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -4574,6 +4857,9 @@
     src/core/ext/census/resource.c \
     src/core/ext/census/trace_context.c \
     src/core/ext/census/tracing.c \
+    third_party/nanopb/pb_common.c \
+    third_party/nanopb/pb_decode.c \
+    third_party/nanopb/pb_encode.c \
 
 PUBLIC_HEADERS_CXX += \
     include/grpc++/alarm.h \
@@ -4621,6 +4907,62 @@
     include/grpc++/support/stub_options.h \
     include/grpc++/support/sync_stream.h \
     include/grpc++/support/time.h \
+    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/avl.h \
+    include/grpc/support/cmdline.h \
+    include/grpc/support/cpu.h \
+    include/grpc/support/histogram.h \
+    include/grpc/support/host_port.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/subprocess.h \
+    include/grpc/support/sync.h \
+    include/grpc/support/sync_generic.h \
+    include/grpc/support/sync_posix.h \
+    include/grpc/support/sync_windows.h \
+    include/grpc/support/thd.h \
+    include/grpc/support/time.h \
+    include/grpc/support/tls.h \
+    include/grpc/support/tls_gcc.h \
+    include/grpc/support/tls_msvc.h \
+    include/grpc/support/tls_pthread.h \
+    include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h \
+    include/grpc/impl/codegen/compression_types.h \
+    include/grpc/impl/codegen/connectivity_state.h \
+    include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h \
     include/grpc++/impl/codegen/async_unary_call.h \
     include/grpc++/impl/codegen/call.h \
@@ -4650,36 +4992,6 @@
     include/grpc++/impl/codegen/stub_options.h \
     include/grpc++/impl/codegen/sync_stream.h \
     include/grpc++/impl/codegen/time.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/exec_ctx_fwd.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/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_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/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/census.h \
 
 LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC))))
@@ -5106,94 +5418,18 @@
 $(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
 
 
-LIBGRPC++_UNSECURE_SRC = \
-    src/cpp/client/insecure_credentials.cc \
-    src/cpp/common/insecure_create_auth_context.cc \
-    src/cpp/server/insecure_server_credentials.cc \
-    src/cpp/client/channel_cc.cc \
-    src/cpp/client/client_context.cc \
-    src/cpp/client/create_channel.cc \
-    src/cpp/client/create_channel_internal.cc \
-    src/cpp/client/create_channel_posix.cc \
-    src/cpp/client/credentials_cc.cc \
-    src/cpp/client/generic_stub.cc \
-    src/cpp/common/channel_arguments.cc \
-    src/cpp/common/channel_filter.cc \
-    src/cpp/common/completion_queue_cc.cc \
-    src/cpp/common/core_codegen.cc \
-    src/cpp/common/resource_quota_cc.cc \
-    src/cpp/common/rpc_method.cc \
-    src/cpp/common/version_cc.cc \
-    src/cpp/server/async_generic_service.cc \
-    src/cpp/server/channel_argument_option.cc \
-    src/cpp/server/create_default_thread_pool.cc \
-    src/cpp/server/dynamic_thread_pool.cc \
-    src/cpp/server/health/default_health_check_service.cc \
-    src/cpp/server/health/health.pb.c \
-    src/cpp/server/health/health_check_service.cc \
-    src/cpp/server/health/health_check_service_server_builder_option.cc \
-    src/cpp/server/server_builder.cc \
-    src/cpp/server/server_cc.cc \
-    src/cpp/server/server_context.cc \
-    src/cpp/server/server_credentials.cc \
-    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 \
-    third_party/nanopb/pb_common.c \
-    third_party/nanopb/pb_decode.c \
-    third_party/nanopb/pb_encode.c \
+LIBGRPC++_TEST_UTIL_UNSECURE_SRC = \
+    $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc \
+    $(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 \
+    $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc \
+    test/cpp/end2end/test_service_impl.cc \
+    test/cpp/util/byte_buffer_proto_helper.cc \
+    test/cpp/util/string_ref_helper.cc \
+    test/cpp/util/subprocess.cc \
     src/cpp/codegen/codegen_init.cc \
 
 PUBLIC_HEADERS_CXX += \
-    include/grpc++/alarm.h \
-    include/grpc++/channel.h \
-    include/grpc++/client_context.h \
-    include/grpc++/completion_queue.h \
-    include/grpc++/create_channel.h \
-    include/grpc++/create_channel_posix.h \
-    include/grpc++/ext/health_check_service_server_builder_option.h \
-    include/grpc++/generic/async_generic_service.h \
-    include/grpc++/generic/generic_stub.h \
-    include/grpc++/grpc++.h \
-    include/grpc++/health_check_service_interface.h \
-    include/grpc++/impl/call.h \
-    include/grpc++/impl/channel_argument_option.h \
-    include/grpc++/impl/client_unary_call.h \
-    include/grpc++/impl/codegen/core_codegen.h \
-    include/grpc++/impl/grpc_library.h \
-    include/grpc++/impl/method_handler_impl.h \
-    include/grpc++/impl/rpc_method.h \
-    include/grpc++/impl/rpc_service_method.h \
-    include/grpc++/impl/serialization_traits.h \
-    include/grpc++/impl/server_builder_option.h \
-    include/grpc++/impl/server_builder_plugin.h \
-    include/grpc++/impl/server_initializer.h \
-    include/grpc++/impl/service_type.h \
-    include/grpc++/resource_quota.h \
-    include/grpc++/security/auth_context.h \
-    include/grpc++/security/auth_metadata_processor.h \
-    include/grpc++/security/credentials.h \
-    include/grpc++/security/server_credentials.h \
-    include/grpc++/server.h \
-    include/grpc++/server_builder.h \
-    include/grpc++/server_context.h \
-    include/grpc++/server_posix.h \
-    include/grpc++/support/async_stream.h \
-    include/grpc++/support/async_unary_call.h \
-    include/grpc++/support/byte_buffer.h \
-    include/grpc++/support/channel_arguments.h \
-    include/grpc++/support/config.h \
-    include/grpc++/support/slice.h \
-    include/grpc++/support/status.h \
-    include/grpc++/support/status_code_enum.h \
-    include/grpc++/support/string_ref.h \
-    include/grpc++/support/stub_options.h \
-    include/grpc++/support/sync_stream.h \
-    include/grpc++/support/time.h \
     include/grpc++/impl/codegen/async_stream.h \
     include/grpc++/impl/codegen/async_unary_call.h \
     include/grpc++/impl/codegen/call.h \
@@ -5242,6 +5478,228 @@
     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/proto_utils.h \
+    include/grpc++/impl/codegen/config_protobuf.h \
+
+LIBGRPC++_TEST_UTIL_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_UNSECURE_SRC))))
+
+
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure libraries if you don't have OpenSSL.
+
+$(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.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)/libgrpc++_test_util_unsecure.a: protobuf_dep_error
+
+
+else
+
+$(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_TEST_UTIL_UNSECURE_OBJS) 
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a
+	$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBGRPC++_TEST_UTIL_UNSECURE_OBJS) 
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a
+endif
+
+
+
+
+endif
+
+endif
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LIBGRPC++_TEST_UTIL_UNSECURE_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/end2end/test_service_impl.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/byte_buffer_proto_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/subprocess.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(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 $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+
+
+LIBGRPC++_UNSECURE_SRC = \
+    src/cpp/client/insecure_credentials.cc \
+    src/cpp/common/insecure_create_auth_context.cc \
+    src/cpp/server/insecure_server_credentials.cc \
+    src/cpp/client/channel_cc.cc \
+    src/cpp/client/client_context.cc \
+    src/cpp/client/create_channel.cc \
+    src/cpp/client/create_channel_internal.cc \
+    src/cpp/client/create_channel_posix.cc \
+    src/cpp/client/credentials_cc.cc \
+    src/cpp/client/generic_stub.cc \
+    src/cpp/common/channel_arguments.cc \
+    src/cpp/common/channel_filter.cc \
+    src/cpp/common/completion_queue_cc.cc \
+    src/cpp/common/core_codegen.cc \
+    src/cpp/common/resource_quota_cc.cc \
+    src/cpp/common/rpc_method.cc \
+    src/cpp/common/version_cc.cc \
+    src/cpp/server/async_generic_service.cc \
+    src/cpp/server/channel_argument_option.cc \
+    src/cpp/server/create_default_thread_pool.cc \
+    src/cpp/server/dynamic_thread_pool.cc \
+    src/cpp/server/health/default_health_check_service.cc \
+    src/cpp/server/health/health.pb.c \
+    src/cpp/server/health/health_check_service.cc \
+    src/cpp/server/health/health_check_service_server_builder_option.cc \
+    src/cpp/server/server_builder.cc \
+    src/cpp/server/server_cc.cc \
+    src/cpp/server/server_context.cc \
+    src/cpp/server/server_credentials.cc \
+    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 \
+
+PUBLIC_HEADERS_CXX += \
+    include/grpc++/alarm.h \
+    include/grpc++/channel.h \
+    include/grpc++/client_context.h \
+    include/grpc++/completion_queue.h \
+    include/grpc++/create_channel.h \
+    include/grpc++/create_channel_posix.h \
+    include/grpc++/ext/health_check_service_server_builder_option.h \
+    include/grpc++/generic/async_generic_service.h \
+    include/grpc++/generic/generic_stub.h \
+    include/grpc++/grpc++.h \
+    include/grpc++/health_check_service_interface.h \
+    include/grpc++/impl/call.h \
+    include/grpc++/impl/channel_argument_option.h \
+    include/grpc++/impl/client_unary_call.h \
+    include/grpc++/impl/codegen/core_codegen.h \
+    include/grpc++/impl/grpc_library.h \
+    include/grpc++/impl/method_handler_impl.h \
+    include/grpc++/impl/rpc_method.h \
+    include/grpc++/impl/rpc_service_method.h \
+    include/grpc++/impl/serialization_traits.h \
+    include/grpc++/impl/server_builder_option.h \
+    include/grpc++/impl/server_builder_plugin.h \
+    include/grpc++/impl/server_initializer.h \
+    include/grpc++/impl/service_type.h \
+    include/grpc++/resource_quota.h \
+    include/grpc++/security/auth_context.h \
+    include/grpc++/security/auth_metadata_processor.h \
+    include/grpc++/security/credentials.h \
+    include/grpc++/security/server_credentials.h \
+    include/grpc++/server.h \
+    include/grpc++/server_builder.h \
+    include/grpc++/server_context.h \
+    include/grpc++/server_posix.h \
+    include/grpc++/support/async_stream.h \
+    include/grpc++/support/async_unary_call.h \
+    include/grpc++/support/byte_buffer.h \
+    include/grpc++/support/channel_arguments.h \
+    include/grpc++/support/config.h \
+    include/grpc++/support/slice.h \
+    include/grpc++/support/status.h \
+    include/grpc++/support/status_code_enum.h \
+    include/grpc++/support/string_ref.h \
+    include/grpc++/support/stub_options.h \
+    include/grpc++/support/sync_stream.h \
+    include/grpc++/support/time.h \
+    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/avl.h \
+    include/grpc/support/cmdline.h \
+    include/grpc/support/cpu.h \
+    include/grpc/support/histogram.h \
+    include/grpc/support/host_port.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/subprocess.h \
+    include/grpc/support/sync.h \
+    include/grpc/support/sync_generic.h \
+    include/grpc/support/sync_posix.h \
+    include/grpc/support/sync_windows.h \
+    include/grpc/support/thd.h \
+    include/grpc/support/time.h \
+    include/grpc/support/tls.h \
+    include/grpc/support/tls_gcc.h \
+    include/grpc/support/tls_msvc.h \
+    include/grpc/support/tls_pthread.h \
+    include/grpc/support/useful.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/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_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/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/impl/codegen/byte_buffer_reader.h \
+    include/grpc/impl/codegen/compression_types.h \
+    include/grpc/impl/codegen/connectivity_state.h \
+    include/grpc/impl/codegen/exec_ctx_fwd.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/async_stream.h \
+    include/grpc++/impl/codegen/async_unary_call.h \
+    include/grpc++/impl/codegen/call.h \
+    include/grpc++/impl/codegen/call_hook.h \
+    include/grpc++/impl/codegen/channel_interface.h \
+    include/grpc++/impl/codegen/client_context.h \
+    include/grpc++/impl/codegen/client_unary_call.h \
+    include/grpc++/impl/codegen/completion_queue.h \
+    include/grpc++/impl/codegen/completion_queue_tag.h \
+    include/grpc++/impl/codegen/config.h \
+    include/grpc++/impl/codegen/core_codegen_interface.h \
+    include/grpc++/impl/codegen/create_auth_context.h \
+    include/grpc++/impl/codegen/grpc_library.h \
+    include/grpc++/impl/codegen/metadata_map.h \
+    include/grpc++/impl/codegen/method_handler_impl.h \
+    include/grpc++/impl/codegen/rpc_method.h \
+    include/grpc++/impl/codegen/rpc_service_method.h \
+    include/grpc++/impl/codegen/security/auth_context.h \
+    include/grpc++/impl/codegen/serialization_traits.h \
+    include/grpc++/impl/codegen/server_context.h \
+    include/grpc++/impl/codegen/server_interface.h \
+    include/grpc++/impl/codegen/service_type.h \
+    include/grpc++/impl/codegen/slice.h \
+    include/grpc++/impl/codegen/status.h \
+    include/grpc++/impl/codegen/status_code_enum.h \
+    include/grpc++/impl/codegen/string_ref.h \
+    include/grpc++/impl/codegen/stub_options.h \
+    include/grpc++/impl/codegen/sync_stream.h \
+    include/grpc++/impl/codegen/time.h \
 
 LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC))))
 
@@ -5268,18 +5726,18 @@
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
+$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll -lgrpc$(SHARED_VERSION_CORE)-dll
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE)
+$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
 endif
@@ -7928,6 +8386,7 @@
     test/core/end2end/tests/payload.c \
     test/core/end2end/tests/ping.c \
     test/core/end2end/tests/ping_pong_streaming.c \
+    test/core/end2end/tests/proxy_auth.c \
     test/core/end2end/tests/registered_call.c \
     test/core/end2end/tests/request_with_flags.c \
     test/core/end2end/tests/request_with_payload.c \
@@ -8022,6 +8481,7 @@
     test/core/end2end/tests/payload.c \
     test/core/end2end/tests/ping.c \
     test/core/end2end/tests/ping_pong_streaming.c \
+    test/core/end2end/tests/proxy_auth.c \
     test/core/end2end/tests/registered_call.c \
     test/core/end2end/tests/request_with_flags.c \
     test/core/end2end/tests/request_with_payload.c \
@@ -8385,6 +8845,38 @@
 endif
 
 
+BYTE_STREAM_TEST_SRC = \
+    test/core/transport/byte_stream_test.c \
+
+BYTE_STREAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BYTE_STREAM_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/byte_stream_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/byte_stream_test: $(BYTE_STREAM_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) $(BYTE_STREAM_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)/byte_stream_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/byte_stream_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_byte_stream_test: $(BYTE_STREAM_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BYTE_STREAM_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 CENSUS_CONTEXT_TEST_SRC = \
     test/core/census/context_test.c \
 
@@ -12257,6 +12749,38 @@
 endif
 
 
+STREAM_COMPRESSION_TEST_SRC = \
+    test/core/compression/stream_compression_test.c \
+
+STREAM_COMPRESSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_COMPRESSION_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/stream_compression_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/stream_compression_test: $(STREAM_COMPRESSION_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) $(STREAM_COMPRESSION_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)/stream_compression_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/compression/stream_compression_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_stream_compression_test: $(STREAM_COMPRESSION_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(STREAM_COMPRESSION_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 STREAM_OWNED_SLICE_TEST_SRC = \
     test/core/transport/stream_owned_slice_test.c \
 
@@ -12856,16 +13380,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/alarm_cpp_test: $(PROTOBUF_DEP) $(ALARM_CPP_TEST_OBJS) $(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
+$(BINDIR)/$(CONFIG)/alarm_cpp_test: $(PROTOBUF_DEP) $(ALARM_CPP_TEST_OBJS) $(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
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(ALARM_CPP_TEST_OBJS) $(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)/alarm_cpp_test
+	$(Q) $(LDXX) $(LDFLAGS) $(ALARM_CPP_TEST_OBJS) $(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)/alarm_cpp_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/common/alarm_cpp_test.o:  $(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
+$(OBJDIR)/$(CONFIG)/test/cpp/common/alarm_cpp_test.o:  $(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
 
 deps_alarm_cpp_test: $(ALARM_CPP_TEST_OBJS:.o=.dep)
 
@@ -12985,17 +13509,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_arena: $(PROTOBUF_DEP) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_arena: $(BM_ARENA_OBJS:.o=.dep)
 
@@ -13029,17 +13553,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_call_create: $(BM_CALL_CREATE_OBJS:.o=.dep)
 
@@ -13073,17 +13597,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_chttp2_hpack: $(BM_CHTTP2_HPACK_OBJS:.o=.dep)
 
@@ -13117,17 +13641,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_chttp2_transport: $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep)
 
@@ -13161,17 +13685,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_closure: $(BM_CLOSURE_OBJS:.o=.dep)
 
@@ -13205,17 +13729,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_cq: $(PROTOBUF_DEP) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_cq: $(BM_CQ_OBJS:.o=.dep)
 
@@ -13249,17 +13773,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_cq_multiple_threads: $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep)
 
@@ -13293,17 +13817,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_error: $(BM_ERROR_OBJS:.o=.dep)
 
@@ -13337,17 +13861,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_fullstack_streaming_ping_pong: $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS:.o=.dep)
 
@@ -13381,17 +13905,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_fullstack_streaming_pump: $(BM_FULLSTACK_STREAMING_PUMP_OBJS:.o=.dep)
 
@@ -13425,17 +13949,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_fullstack_trickle: $(PROTOBUF_DEP) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(BINDIR)/$(CONFIG)/bm_fullstack_trickle: $(PROTOBUF_DEP) $(BM_FULLSTACK_TRICKLE_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
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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)/bm_fullstack_trickle
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_TRICKLE_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_trickle
 
 endif
 
 endif
 
 $(BM_FULLSTACK_TRICKLE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_trickle.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_trickle.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
 
 deps_bm_fullstack_trickle: $(BM_FULLSTACK_TRICKLE_OBJS:.o=.dep)
 
@@ -13469,17 +13993,17 @@
 
 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.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_fullstack_unary_ping_pong: $(BM_FULLSTACK_UNARY_PING_PONG_OBJS:.o=.dep)
 
@@ -13513,17 +14037,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_metadata: $(BM_METADATA_OBJS:.o=.dep)
 
@@ -13557,17 +14081,17 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.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
+$(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
 	$(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.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)/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 $(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.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
+$(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
 
 deps_bm_pollset: $(BM_POLLSET_OBJS:.o=.dep)
 
@@ -15398,16 +15922,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/qps_interarrival_test: $(PROTOBUF_DEP) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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
+$(BINDIR)/$(CONFIG)/qps_interarrival_test: $(PROTOBUF_DEP) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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)/qps_interarrival_test
+	$(Q) $(LDXX) $(LDFLAGS) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_interarrival_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_interarrival_test.o:  $(LIBDIR)/$(CONFIG)/libqps.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
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_interarrival_test.o:  $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_qps_interarrival_test: $(QPS_INTERARRIVAL_TEST_OBJS:.o=.dep)
 
@@ -15719,16 +16243,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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
+$(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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)/secure_sync_unary_ping_pong_test
+	$(Q) $(LDXX) $(LDFLAGS) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/secure_sync_unary_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.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
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/secure_sync_unary_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_secure_sync_unary_ping_pong_test: $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
 
@@ -15807,20 +16331,20 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/server_builder_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/server_builder_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_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_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_test
+	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_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_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(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.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.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_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_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_test: $(SERVER_BUILDER_TEST_OBJS:.o=.dep)
 
@@ -15961,6 +16485,56 @@
 endif
 
 
+SERVER_REQUEST_CALL_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_request_call_test.cc \
+
+SERVER_REQUEST_CALL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_REQUEST_CALL_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_request_call_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.0.0+.
+
+$(BINDIR)/$(CONFIG)/server_request_call_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/server_request_call_test: $(PROTOBUF_DEP) $(SERVER_REQUEST_CALL_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_REQUEST_CALL_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_request_call_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_request_call_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_request_call_test: $(SERVER_REQUEST_CALL_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_REQUEST_CALL_TEST_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/server/server_request_call_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
+
+
 SHUTDOWN_TEST_SRC = \
     test/cpp/end2end/shutdown_test.cc \
 
@@ -16181,16 +16755,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/thread_manager_test: $(PROTOBUF_DEP) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(BINDIR)/$(CONFIG)/thread_manager_test: $(PROTOBUF_DEP) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/thread_manager_test
+	$(Q) $(LDXX) $(LDFLAGS) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/thread_manager_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/thread_manager/thread_manager_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(OBJDIR)/$(CONFIG)/test/cpp/thread_manager/thread_manager_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_thread_manager_test: $(THREAD_MANAGER_TEST_OBJS:.o=.dep)
 
@@ -16224,16 +16798,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/thread_stress_test: $(PROTOBUF_DEP) $(THREAD_STRESS_TEST_OBJS) $(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
+$(BINDIR)/$(CONFIG)/thread_stress_test: $(PROTOBUF_DEP) $(THREAD_STRESS_TEST_OBJS) $(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
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(THREAD_STRESS_TEST_OBJS) $(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)/thread_stress_test
+	$(Q) $(LDXX) $(LDFLAGS) $(THREAD_STRESS_TEST_OBJS) $(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)/thread_stress_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/end2end/thread_stress_test.o:  $(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
+$(OBJDIR)/$(CONFIG)/test/cpp/end2end/thread_stress_test.o:  $(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
 
 deps_thread_stress_test: $(THREAD_STRESS_TEST_OBJS:.o=.dep)
 
@@ -18297,6 +18871,38 @@
 endif
 
 
+INPROC_TEST_SRC = \
+    test/core/end2end/fixtures/inproc.c \
+
+INPROC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/inproc_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/inproc_test: $(INPROC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(INPROC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/inproc_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/inproc.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_inproc_test: $(INPROC_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(INPROC_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 H2_CENSUS_NOSEC_TEST_SRC = \
     test/core/end2end/fixtures/h2_census.c \
 
@@ -18577,6 +19183,26 @@
 endif
 
 
+INPROC_NOSEC_TEST_SRC = \
+    test/core/end2end/fixtures/inproc.c \
+
+INPROC_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_NOSEC_TEST_SRC))))
+
+
+$(BINDIR)/$(CONFIG)/inproc_nosec_test: $(INPROC_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(INPROC_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/inproc_nosec_test
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/inproc.o:  $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_inproc_nosec_test: $(INPROC_NOSEC_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(INPROC_NOSEC_TEST_OBJS:.o=.dep)
+endif
+
+
 API_FUZZER_ONE_ENTRY_SRC = \
     test/core/end2end/fuzzers/api_fuzzer.c \
     test/core/util/one_corpus_entry_fuzzer.c \
@@ -19073,6 +19699,7 @@
 src/core/plugin_registry/grpc_cronet_plugin_registry.c: $(OPENSSL_DEP)
 src/core/plugin_registry/grpc_plugin_registry.c: $(OPENSSL_DEP)
 src/core/tsi/fake_transport_security.c: $(OPENSSL_DEP)
+src/core/tsi/gts_transport_security.c: $(OPENSSL_DEP)
 src/core/tsi/ssl_transport_security.c: $(OPENSSL_DEP)
 src/core/tsi/transport_security.c: $(OPENSSL_DEP)
 src/core/tsi/transport_security_adapter.c: $(OPENSSL_DEP)
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..650d58f
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,17 @@
+# Top level ownership
+
+# nothing listed here until GitHub CODEOWNERS gets better
+# we need:
+# 1. owners to be able to self-approve
+# 2. authors to be able to select approvers
+
+# OWNERS file approvers
+# POLICY: at least three owners are needed before adding any OWNERS
+# REASON: GitHub does not recognize an author as able to give approval
+#         for a change; without this policy authors that are owners would
+#         be forced to rely on one reviewer, which would consequently
+#         lead to a bus factor of one to changes to that code
+@markdroth **/OWNERS
+@nicolasnoble **/OWNERS
+@ctiller **/OWNERS
+
diff --git a/README.md b/README.md
index 0edea88..995f877 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
 
 See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks)
 
-See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5712453606309888) for the performance numbers for v1.0.x.
+See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5636470266134528) for the performance numbers for the latest released version.
 
 # Repository Structure & Status
 
diff --git a/bazel/OWNERS b/bazel/OWNERS
new file mode 100644
index 0000000..8fc7502
--- /dev/null
+++ b/bazel/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+@nicolasnoble
+@dgquintas
+@ctiller
+
diff --git a/bazel/cc_grpc_library.bzl b/bazel/cc_grpc_library.bzl
index 0600bb9..afc5543 100644
--- a/bazel/cc_grpc_library.bzl
+++ b/bazel/cc_grpc_library.bzl
@@ -12,9 +12,8 @@
       srcs: a single proto_library, which wraps the .proto files with services.
       deps: a list of C++ proto_library (or cc_proto_library) which provides
         the compiled code of any message that the services depend on.
-      well_known_protos: The target from protobuf library that exports well
-        known protos. Currently it will only work if the value is
-        "@com_google_protobuf//:well_known_protos"
+      well_known_protos: Should this library additionally depend on well known
+        protos
       use_external: When True the grpc deps are prefixed with //external. This
         allows grpc to be used as a dependency in other bazel projects.
       generate_mock: When true GMOCk code for client stub is generated.
diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl
index d05509f..7fffb58 100644
--- a/bazel/generate_cc.bzl
+++ b/bazel/generate_cc.bzl
@@ -57,7 +57,7 @@
 
   return struct(files=set(out_files))
 
-generate_cc = rule(
+_generate_cc = rule(
     attrs = {
         "srcs": attr.label_list(
             mandatory = True,
@@ -90,3 +90,9 @@
     output_to_genfiles = True,
     implementation = generate_cc_impl,
 )
+
+def generate_cc(well_known_protos, **kwargs):
+  if well_known_protos:
+    _generate_cc(well_known_protos="@com_google_protobuf//:well_known_protos", **kwargs)
+  else:
+    _generate_cc(**kwargs)
diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl
index 8c29611..0295adb 100644
--- a/bazel/grpc_build_system.bzl
+++ b/bazel/grpc_build_system.bzl
@@ -25,7 +25,8 @@
 
 def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
                     external_deps = [], deps = [], standalone = False,
-                    language = "C++", testonly = False, visibility = None):
+                    language = "C++", testonly = False, visibility = None,
+                    alwayslink = 0):
   copts = []
   if language.upper() == "C":
     copts = ["-std=c99"]
@@ -40,7 +41,8 @@
     linkopts = ["-pthread"],
     includes = [
         "include"
-    ]
+    ],
+    alwayslink = alwayslink,
   )
 
 def grpc_proto_plugin(name, srcs = [], deps = []):
@@ -52,7 +54,7 @@
 
 load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library")
 
-def grpc_proto_library(name, srcs = [], deps = [], well_known_protos = None,
+def grpc_proto_library(name, srcs = [], deps = [], well_known_protos = False,
                        has_services = True, use_external = False, generate_mock = False):
   cc_grpc_library(
     name = name,
@@ -78,7 +80,7 @@
     linkopts = ["-pthread"],
   )
 
-def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False):
+def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = []):
   copts = []
   if language.upper() == "C":
     copts = ["-std=c99"]
@@ -91,15 +93,15 @@
     linkshared = linkshared,
     deps = deps + ["//external:" + dep for dep in external_deps],
     copts = copts,
-    linkopts = ["-pthread"],
+    linkopts = ["-pthread"] + linkopts,
   )
 
 def grpc_generate_one_off_targets():
-    pass
+  pass
 
 def grpc_sh_test(name, srcs, args = [], data = []):
-    native.sh_test(
-        name = name,
-        srcs = srcs,
-        args = args,
-        data = data)
+  native.sh_test(
+    name = name,
+    srcs = srcs,
+    args = args,
+    data = data)
diff --git a/binding.gyp b/binding.gyp
index 0b581b3..8a2900b 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -175,21 +175,28 @@
       }],
       ['OS == "mac"', {
         'xcode_settings': {
-          'MACOSX_DEPLOYMENT_TARGET': '10.9'
+          'OTHER_CFLAGS': [
+              '-g',
+              '-Wall',
+              '-Wextra',
+              '-Werror',
+              '-Wno-long-long',
+              '-Wno-unused-parameter',
+              '-DOSATOMIC_USE_INLINED=1',
+          ],
+          'OTHER_CPLUSPLUSFLAGS': [
+              '-g',
+              '-Wall',
+              '-Wextra',
+              '-Werror',
+              '-Wno-long-long',
+              '-Wno-unused-parameter',
+              '-DOSATOMIC_USE_INLINED=1',
+            '-stdlib=libc++',
+            '-std=c++11',
+            '-Wno-error=deprecated-declarations'
+          ],
         },
-        'OTHER_CFLAGS': [
-            '-g',
-            '-Wall',
-            '-Wextra',
-            '-Werror',
-            '-Wno-long-long',
-            '-Wno-unused-parameter',
-            '-DOSATOMIC_USE_INLINED=1',
-        ],
-        'OTHER_CPLUSPLUSFLAGS': [
-          '-stdlib=libc++',
-          '-std=c++11'
-        ],
       }]
     ]
   },
@@ -508,6 +515,13 @@
             'third_party/boringssl/ssl/tls_method.c',
             'third_party/boringssl/ssl/tls_record.c',
           ],
+          'conditions': [
+            ['OS == "mac"', {
+              'xcode_settings': {
+                'MACOSX_DEPLOYMENT_TARGET': '10.9'
+              }
+            }]
+          ]
         },
       ],
     }],
@@ -626,6 +640,13 @@
         'src/core/lib/support/tmpfile_windows.c',
         'src/core/lib/support/wrap_memcpy.c',
       ],
+      'conditions': [
+        ['OS == "mac"', {
+          'xcode_settings': {
+            'MACOSX_DEPLOYMENT_TARGET': '10.9'
+          }
+        }]
+      ]
     },
     {
       'target_name': 'grpc',
@@ -645,6 +666,7 @@
         'src/core/lib/channel/handshaker_registry.c',
         'src/core/lib/compression/compression.c',
         'src/core/lib/compression/message_compress.c',
+        'src/core/lib/compression/stream_compression.c',
         'src/core/lib/http/format_request.c',
         'src/core/lib/http/httpcli.c',
         'src/core/lib/http/parser.c',
@@ -766,6 +788,7 @@
         'src/core/ext/transport/chttp2/transport/bin_encoder.c',
         'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
         'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+        'src/core/ext/transport/chttp2/transport/flow_control.c',
         'src/core/ext/transport/chttp2/transport/frame_data.c',
         'src/core/ext/transport/chttp2/transport/frame_goaway.c',
         'src/core/ext/transport/chttp2/transport/frame_ping.c',
@@ -813,6 +836,7 @@
         'src/core/lib/security/util/json_util.c',
         'src/core/lib/surface/init_secure.c',
         'src/core/tsi/fake_transport_security.c',
+        'src/core/tsi/gts_transport_security.c',
         'src/core/tsi/ssl_transport_security.c',
         'src/core/tsi/transport_security.c',
         'src/core/tsi/transport_security_adapter.c',
@@ -844,6 +868,8 @@
         'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
+        'src/core/ext/transport/inproc/inproc_plugin.c',
+        'src/core/ext/transport/inproc/inproc_transport.c',
         'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c',
         'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c',
         'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c',
@@ -885,6 +911,13 @@
         'src/core/ext/filters/workarounds/workaround_utils.c',
         'src/core/plugin_registry/grpc_plugin_registry.c',
       ],
+      'conditions': [
+        ['OS == "mac"', {
+          'xcode_settings': {
+            'MACOSX_DEPLOYMENT_TARGET': '10.9'
+          }
+        }]
+      ]
     },
     {
       'include_dirs': [
@@ -910,6 +943,11 @@
           'ldflags': [
             '-Wl,-wrap,memcpy'
           ]
+        }],
+        ['OS == "mac"', {
+          'xcode_settings': {
+            'MACOSX_DEPLOYMENT_TARGET': '10.9'
+          }
         }]
       ],
       "target_name": "grpc_node",
diff --git a/build.yaml b/build.yaml
index e55c4ca..81bcf44 100644
--- a/build.yaml
+++ b/build.yaml
@@ -59,52 +59,6 @@
   - grpc_base
   - nanopb
 - name: gpr_base
-  public_headers:
-  - 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/avl.h
-  - include/grpc/support/cmdline.h
-  - include/grpc/support/cpu.h
-  - include/grpc/support/histogram.h
-  - include/grpc/support/host_port.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/subprocess.h
-  - include/grpc/support/sync.h
-  - include/grpc/support/sync_generic.h
-  - include/grpc/support/sync_posix.h
-  - include/grpc/support/sync_windows.h
-  - include/grpc/support/thd.h
-  - include/grpc/support/time.h
-  - include/grpc/support/tls.h
-  - include/grpc/support/tls_gcc.h
-  - include/grpc/support/tls_msvc.h
-  - include/grpc/support/tls_pthread.h
-  - include/grpc/support/useful.h
-  headers:
-  - src/core/lib/profiling/timers.h
-  - src/core/lib/support/arena.h
-  - src/core/lib/support/atomic.h
-  - src/core/lib/support/atomic_with_atm.h
-  - src/core/lib/support/atomic_with_std.h
-  - src/core/lib/support/backoff.h
-  - src/core/lib/support/block_annotate.h
-  - src/core/lib/support/env.h
-  - src/core/lib/support/memory.h
-  - src/core/lib/support/mpscq.h
-  - src/core/lib/support/murmur_hash.h
-  - src/core/lib/support/spinlock.h
-  - src/core/lib/support/stack_lockfree.h
-  - src/core/lib/support/string.h
-  - src/core/lib/support/string_windows.h
-  - src/core/lib/support/thd_internal.h
-  - src/core/lib/support/time_precise.h
-  - src/core/lib/support/tmpfile.h
   src:
   - src/core/lib/profiling/basic_timers.c
   - src/core/lib/profiling/stap_timers.c
@@ -153,6 +107,55 @@
   - src/core/lib/support/tmpfile_windows.c
   - src/core/lib/support/wrap_memcpy.c
   uses:
+  - gpr_base_headers
+- name: gpr_base_headers
+  public_headers:
+  - 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/avl.h
+  - include/grpc/support/cmdline.h
+  - include/grpc/support/cpu.h
+  - include/grpc/support/histogram.h
+  - include/grpc/support/host_port.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/subprocess.h
+  - include/grpc/support/sync.h
+  - include/grpc/support/sync_generic.h
+  - include/grpc/support/sync_posix.h
+  - include/grpc/support/sync_windows.h
+  - include/grpc/support/thd.h
+  - include/grpc/support/time.h
+  - include/grpc/support/tls.h
+  - include/grpc/support/tls_gcc.h
+  - include/grpc/support/tls_msvc.h
+  - include/grpc/support/tls_pthread.h
+  - include/grpc/support/useful.h
+  headers:
+  - src/core/lib/profiling/timers.h
+  - src/core/lib/support/arena.h
+  - src/core/lib/support/atomic.h
+  - src/core/lib/support/atomic_with_atm.h
+  - src/core/lib/support/atomic_with_std.h
+  - src/core/lib/support/backoff.h
+  - src/core/lib/support/block_annotate.h
+  - src/core/lib/support/env.h
+  - src/core/lib/support/memory.h
+  - src/core/lib/support/mpscq.h
+  - src/core/lib/support/murmur_hash.h
+  - src/core/lib/support/spinlock.h
+  - src/core/lib/support/stack_lockfree.h
+  - src/core/lib/support/string.h
+  - src/core/lib/support/string_windows.h
+  - src/core/lib/support/thd_internal.h
+  - src/core/lib/support/time_precise.h
+  - src/core/lib/support/tmpfile.h
+  uses:
   - gpr_codegen
 - name: gpr_codegen
   public_headers:
@@ -167,129 +170,19 @@
   - include/grpc/impl/codegen/sync_generic.h
   - include/grpc/impl/codegen/sync_posix.h
   - include/grpc/impl/codegen/sync_windows.h
+- name: grpc++_base
+  deps:
+  - grpc
+  uses:
+  - grpc++_common
+  - grpc++_codegen_base
+- name: grpc++_base_unsecure
+  deps:
+  - grpc_unsecure
+  uses:
+  - grpc++_common
+  - grpc++_codegen_base
 - name: grpc_base
-  public_headers:
-  - include/grpc/byte_buffer.h
-  - include/grpc/byte_buffer_reader.h
-  - include/grpc/compression.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
-  headers:
-  - 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/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/compression/algorithm_metadata.h
-  - src/core/lib/compression/message_compress.h
-  - src/core/lib/http/format_request.h
-  - src/core/lib/http/httpcli.h
-  - src/core/lib/http/parser.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_epoll_limited_pollers_linux.h
-  - src/core/lib/iomgr/ev_epoll_thread_pool_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/iocp_windows.h
-  - src/core/lib/iomgr/iomgr.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/network_status_tracker.h
-  - src/core/lib/iomgr/polling_entity.h
-  - src/core/lib/iomgr/pollset.h
-  - src/core/lib/iomgr/pollset_set.h
-  - src/core/lib/iomgr/pollset_set_windows.h
-  - src/core/lib/iomgr/pollset_uv.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/resource_quota.h
-  - src/core/lib/iomgr/sockaddr.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_posix.h
-  - src/core/lib/iomgr/tcp_server.h
-  - src/core/lib/iomgr/tcp_server_utils_posix.h
-  - src/core/lib/iomgr/tcp_uv.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_generic.h
-  - src/core/lib/iomgr/timer_heap.h
-  - src/core/lib/iomgr/timer_manager.h
-  - src/core/lib/iomgr/timer_uv.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/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/timeout_encoding.h
-  - src/core/lib/transport/transport.h
-  - src/core/lib/transport/transport_impl.h
   src:
   - src/core/lib/channel/channel_args.c
   - src/core/lib/channel/channel_stack.c
@@ -300,6 +193,7 @@
   - src/core/lib/channel/handshaker_registry.c
   - src/core/lib/compression/compression.c
   - src/core/lib/compression/message_compress.c
+  - src/core/lib/compression/stream_compression.c
   - src/core/lib/http/format_request.c
   - src/core/lib/http/httpcli.c
   - src/core/lib/http/parser.c
@@ -417,9 +311,142 @@
   - src/core/lib/transport/transport_op_string.c
   deps:
   - gpr
+  filegroups:
+  - grpc_base_headers
   uses:
   - grpc_codegen
   - grpc_trace
+- name: grpc_base_headers
+  public_headers:
+  - include/grpc/byte_buffer.h
+  - include/grpc/byte_buffer_reader.h
+  - include/grpc/compression.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
+  headers:
+  - 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/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/compression/algorithm_metadata.h
+  - src/core/lib/compression/message_compress.h
+  - src/core/lib/compression/stream_compression.h
+  - src/core/lib/http/format_request.h
+  - src/core/lib/http/httpcli.h
+  - src/core/lib/http/parser.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_epoll_limited_pollers_linux.h
+  - src/core/lib/iomgr/ev_epoll_thread_pool_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/iocp_windows.h
+  - src/core/lib/iomgr/iomgr.h
+  - src/core/lib/iomgr/iomgr_internal.h
+  - src/core/lib/iomgr/iomgr_posix.h
+  - src/core/lib/iomgr/iomgr_uv.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_set.h
+  - src/core/lib/iomgr/pollset_set_windows.h
+  - src/core/lib/iomgr/pollset_uv.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/resource_quota.h
+  - src/core/lib/iomgr/sockaddr.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_posix.h
+  - src/core/lib/iomgr/tcp_server.h
+  - src/core/lib/iomgr/tcp_server_utils_posix.h
+  - src/core/lib/iomgr/tcp_uv.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_generic.h
+  - src/core/lib/iomgr/timer_heap.h
+  - src/core/lib/iomgr/timer_manager.h
+  - src/core/lib/iomgr/timer_uv.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/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/timeout_encoding.h
+  - src/core/lib/transport/transport.h
+  - src/core/lib/transport/transport_impl.h
+  deps:
+  - gpr
+  uses:
+  - grpc_codegen
+  - grpc_trace_headers
 - name: grpc_client_channel
   headers:
   - src/core/ext/filters/client_channel/client_channel.h
@@ -712,15 +739,23 @@
   - test/core/util/slice_splitter.c
   - test/core/util/trickle_endpoint.c
   deps:
-  - grpc
   - gpr_test_util
+  uses:
+  - grpc_base
+  - grpc_client_channel
+  - grpc_transport_chttp2
 - name: grpc_trace
-  headers:
-  - src/core/lib/debug/trace.h
   src:
   - src/core/lib/debug/trace.c
   deps:
   - gpr
+  filegroups:
+  - grpc_trace_headers
+- name: grpc_trace_headers
+  headers:
+  - src/core/lib/debug/trace.h
+  deps:
+  - gpr
 - name: grpc_transport_chttp2
   headers:
   - src/core/ext/transport/chttp2/transport/bin_decoder.h
@@ -747,6 +782,7 @@
   - src/core/ext/transport/chttp2/transport/bin_encoder.c
   - src/core/ext/transport/chttp2/transport/chttp2_plugin.c
   - src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  - src/core/ext/transport/chttp2/transport/flow_control.c
   - src/core/ext/transport/chttp2/transport/frame_data.c
   - src/core/ext/transport/chttp2/transport/frame_goaway.c
   - src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -843,6 +879,19 @@
   - grpc_base
   - grpc_transport_chttp2
   - grpc_http_filters
+- name: grpc_transport_inproc
+  src:
+  - src/core/ext/transport/inproc/inproc_plugin.c
+  - src/core/ext/transport/inproc/inproc_transport.c
+  plugin: grpc_inproc_plugin
+  uses:
+  - grpc_transport_inproc_headers
+  - grpc_base
+- name: grpc_transport_inproc_headers
+  headers:
+  - src/core/ext/transport/inproc/inproc_transport.h
+  uses:
+  - grpc_base_headers
 - name: grpc_workaround_cronet_compression_filter
   headers:
   - src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h
@@ -853,18 +902,22 @@
   - grpc_base
   - grpc_server_backward_compatibility
 - name: nanopb
+  src:
+  - third_party/nanopb/pb_common.c
+  - third_party/nanopb/pb_decode.c
+  - third_party/nanopb/pb_encode.c
+  filegroups:
+  - nanopb_headers
+- name: nanopb_headers
   headers:
   - third_party/nanopb/pb.h
   - third_party/nanopb/pb_common.h
   - third_party/nanopb/pb_decode.h
   - third_party/nanopb/pb_encode.h
-  src:
-  - third_party/nanopb/pb_common.c
-  - third_party/nanopb/pb_decode.c
-  - third_party/nanopb/pb_encode.c
 - name: tsi
   headers:
   - src/core/tsi/fake_transport_security.h
+  - src/core/tsi/gts_transport_security.h
   - src/core/tsi/ssl_transport_security.h
   - src/core/tsi/ssl_types.h
   - src/core/tsi/transport_security.h
@@ -872,15 +925,65 @@
   - src/core/tsi/transport_security_interface.h
   src:
   - src/core/tsi/fake_transport_security.c
+  - src/core/tsi/gts_transport_security.c
   - src/core/tsi/ssl_transport_security.c
   - src/core/tsi/transport_security.c
   - src/core/tsi/transport_security_adapter.c
   deps:
   - gpr
+  plugin: grpc_tsi_gts
   secure: true
   uses:
   - grpc_trace
-- name: grpc++_base
+  - grpc_base
+- name: grpc++_codegen_base
+  language: c++
+  public_headers:
+  - include/grpc++/impl/codegen/async_stream.h
+  - include/grpc++/impl/codegen/async_unary_call.h
+  - include/grpc++/impl/codegen/call.h
+  - include/grpc++/impl/codegen/call_hook.h
+  - include/grpc++/impl/codegen/channel_interface.h
+  - include/grpc++/impl/codegen/client_context.h
+  - include/grpc++/impl/codegen/client_unary_call.h
+  - include/grpc++/impl/codegen/completion_queue.h
+  - include/grpc++/impl/codegen/completion_queue_tag.h
+  - include/grpc++/impl/codegen/config.h
+  - include/grpc++/impl/codegen/core_codegen_interface.h
+  - include/grpc++/impl/codegen/create_auth_context.h
+  - include/grpc++/impl/codegen/grpc_library.h
+  - include/grpc++/impl/codegen/metadata_map.h
+  - include/grpc++/impl/codegen/method_handler_impl.h
+  - include/grpc++/impl/codegen/rpc_method.h
+  - include/grpc++/impl/codegen/rpc_service_method.h
+  - include/grpc++/impl/codegen/security/auth_context.h
+  - include/grpc++/impl/codegen/serialization_traits.h
+  - include/grpc++/impl/codegen/server_context.h
+  - include/grpc++/impl/codegen/server_interface.h
+  - include/grpc++/impl/codegen/service_type.h
+  - include/grpc++/impl/codegen/slice.h
+  - include/grpc++/impl/codegen/status.h
+  - include/grpc++/impl/codegen/status_code_enum.h
+  - include/grpc++/impl/codegen/string_ref.h
+  - include/grpc++/impl/codegen/stub_options.h
+  - include/grpc++/impl/codegen/sync_stream.h
+  - include/grpc++/impl/codegen/time.h
+  uses:
+  - grpc_codegen
+- name: grpc++_codegen_base_src
+  language: c++
+  src:
+  - src/cpp/codegen/codegen_init.cc
+  uses:
+  - grpc++_codegen_base
+- name: grpc++_codegen_proto
+  language: c++
+  public_headers:
+  - include/grpc++/impl/codegen/proto_utils.h
+  uses:
+  - grpc++_codegen_base
+  - grpc++_config_proto
+- name: grpc++_common
   language: c++
   public_headers:
   - include/grpc++/alarm.h
@@ -970,58 +1073,12 @@
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time_cc.cc
-  deps:
-  - grpc
   uses:
+  - gpr_base_headers
+  - grpc_base_headers
+  - grpc_transport_inproc_headers
   - grpc++_codegen_base
-  - nanopb
-- name: grpc++_codegen_base
-  language: c++
-  public_headers:
-  - include/grpc++/impl/codegen/async_stream.h
-  - include/grpc++/impl/codegen/async_unary_call.h
-  - include/grpc++/impl/codegen/call.h
-  - include/grpc++/impl/codegen/call_hook.h
-  - include/grpc++/impl/codegen/channel_interface.h
-  - include/grpc++/impl/codegen/client_context.h
-  - include/grpc++/impl/codegen/client_unary_call.h
-  - include/grpc++/impl/codegen/completion_queue.h
-  - include/grpc++/impl/codegen/completion_queue_tag.h
-  - include/grpc++/impl/codegen/config.h
-  - include/grpc++/impl/codegen/core_codegen_interface.h
-  - include/grpc++/impl/codegen/create_auth_context.h
-  - include/grpc++/impl/codegen/grpc_library.h
-  - include/grpc++/impl/codegen/metadata_map.h
-  - include/grpc++/impl/codegen/method_handler_impl.h
-  - include/grpc++/impl/codegen/rpc_method.h
-  - include/grpc++/impl/codegen/rpc_service_method.h
-  - include/grpc++/impl/codegen/security/auth_context.h
-  - include/grpc++/impl/codegen/serialization_traits.h
-  - include/grpc++/impl/codegen/server_context.h
-  - include/grpc++/impl/codegen/server_interface.h
-  - include/grpc++/impl/codegen/service_type.h
-  - include/grpc++/impl/codegen/slice.h
-  - include/grpc++/impl/codegen/status.h
-  - include/grpc++/impl/codegen/status_code_enum.h
-  - include/grpc++/impl/codegen/string_ref.h
-  - include/grpc++/impl/codegen/stub_options.h
-  - include/grpc++/impl/codegen/sync_stream.h
-  - include/grpc++/impl/codegen/time.h
-  uses:
-  - grpc_codegen
-- name: grpc++_codegen_base_src
-  language: c++
-  src:
-  - src/cpp/codegen/codegen_init.cc
-  uses:
-  - grpc++_codegen_base
-- name: grpc++_codegen_proto
-  language: c++
-  public_headers:
-  - include/grpc++/impl/codegen/proto_utils.h
-  uses:
-  - grpc++_codegen_base
-  - grpc++_config_proto
+  - nanopb_headers
 - name: grpc++_config_proto
   language: c++
   public_headers:
@@ -1071,6 +1128,7 @@
   - grpc_transport_chttp2_client_secure
   - grpc_transport_chttp2_server_insecure
   - grpc_transport_chttp2_client_insecure
+  - grpc_transport_inproc
   - grpc_lb_policy_grpclb_secure
   - grpc_lb_policy_pick_first
   - grpc_lb_policy_round_robin
@@ -1148,7 +1206,6 @@
   - grpc
   filegroups:
   - grpc_test_util_base
-  - grpc_base
   vs_project_guid: '{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}'
 - name: grpc_test_util_unsecure
   build: private
@@ -1174,6 +1231,7 @@
   - grpc_base
   - grpc_transport_chttp2_server_insecure
   - grpc_transport_chttp2_client_insecure
+  - grpc_transport_inproc
   - grpc_resolver_dns_ares
   - grpc_resolver_dns_native
   - grpc_resolver_sockaddr
@@ -1344,6 +1402,32 @@
   - grpc++_codegen_base_src
   - grpc++_codegen_proto
   - grpc++_config_proto
+- name: grpc++_test_util_unsecure
+  build: private
+  language: c++
+  headers:
+  - test/cpp/end2end/test_service_impl.h
+  - test/cpp/util/byte_buffer_proto_helper.h
+  - test/cpp/util/string_ref_helper.h
+  - test/cpp/util/subprocess.h
+  src:
+  - src/proto/grpc/health/v1/health.proto
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/echo.proto
+  - src/proto/grpc/testing/duplicate/echo_duplicate.proto
+  - test/cpp/end2end/test_service_impl.cc
+  - test/cpp/util/byte_buffer_proto_helper.cc
+  - test/cpp/util/string_ref_helper.cc
+  - test/cpp/util/subprocess.cc
+  deps:
+  - grpc++_unsecure
+  - grpc_test_util_unsecure
+  - grpc_unsecure
+  filegroups:
+  - grpc++_codegen_base
+  - grpc++_codegen_base_src
+  - grpc++_codegen_proto
+  - grpc++_config_proto
 - name: grpc++_unsecure
   build: all
   language: c++
@@ -1357,7 +1441,7 @@
   baselib: true
   dll: true
   filegroups:
-  - grpc++_base
+  - grpc++_base_unsecure
   - grpc++_codegen_base
   - grpc++_codegen_base_src
   secure: false
@@ -1373,9 +1457,9 @@
   - test/cpp/microbenchmarks/helpers.cc
   deps:
   - benchmark
-  - grpc++
-  - grpc_test_util
-  - grpc
+  - grpc++_unsecure
+  - grpc_test_util_unsecure
+  - grpc_unsecure
   defaults: benchmark
 - name: grpc_cli_libs
   build: private
@@ -1684,6 +1768,16 @@
   deps:
   - grpc_test_util
   - grpc
+- name: byte_stream_test
+  build: test
+  language: c
+  src:
+  - test/core/transport/byte_stream_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: census_context_test
   build: test
   language: c
@@ -2369,6 +2463,8 @@
   - grpc
   - gpr_test_util
   - gpr
+  exclude_iomgrs:
+  - uv
   platforms:
   - linux
   secure: true
@@ -2998,6 +3094,16 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: stream_compression_test
+  build: test
+  language: c
+  src:
+  - test/core/compression/stream_compression_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: stream_owned_slice_test
   build: test
   language: c
@@ -3233,10 +3339,10 @@
   src:
   - test/cpp/common/alarm_cpp_test.cc
   deps:
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
 - name: async_end2end_test
@@ -3273,10 +3379,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3294,10 +3400,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3315,10 +3421,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3336,10 +3442,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3357,10 +3463,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3378,10 +3484,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3399,10 +3505,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3420,10 +3526,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3441,10 +3547,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3466,10 +3572,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3491,10 +3597,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3516,10 +3622,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3541,10 +3647,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -3562,10 +3668,10 @@
   deps:
   - grpc_benchmark
   - benchmark
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
   args:
@@ -4162,6 +4268,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   platforms:
   - mac
   - linux
@@ -4280,6 +4387,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   platforms:
   - mac
   - linux
@@ -4306,11 +4414,11 @@
   - src/proto/grpc/testing/echo.proto
   - test/cpp/server/server_builder_test.cc
   deps:
-  - grpc++_test_util
-  - grpc_test_util
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
   - gpr_test_util
-  - grpc++
-  - grpc
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr
 - name: server_context_test_spouse_test
   gtest: true
@@ -4357,6 +4465,21 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: server_request_call_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_request_call_test.cc
+  deps:
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - gpr_test_util
+  - grpc++_unsecure
+  - grpc_unsecure
+  - gpr
 - name: shutdown_test
   gtest: true
   build: test
@@ -4431,8 +4554,8 @@
   src:
   - test/cpp/thread_manager/thread_manager_test.cc
   deps:
-  - grpc++
-  - grpc
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr
   - grpc++_test_config
 - name: thread_stress_test
@@ -4443,12 +4566,13 @@
   src:
   - test/cpp/end2end/thread_stress_test.cc
   deps:
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - grpc++_unsecure
+  - grpc_unsecure
   - gpr_test_util
   - gpr
+  timeout_seconds: 1200
 - name: writes_per_rpc_test
   gtest: true
   cpu_cost: 0.5
diff --git a/config.m4 b/config.m4
index d3a5dc4..c5332f1 100644
--- a/config.m4
+++ b/config.m4
@@ -95,6 +95,7 @@
     src/core/lib/channel/handshaker_registry.c \
     src/core/lib/compression/compression.c \
     src/core/lib/compression/message_compress.c \
+    src/core/lib/compression/stream_compression.c \
     src/core/lib/http/format_request.c \
     src/core/lib/http/httpcli.c \
     src/core/lib/http/parser.c \
@@ -216,6 +217,7 @@
     src/core/ext/transport/chttp2/transport/bin_encoder.c \
     src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
     src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/flow_control.c \
     src/core/ext/transport/chttp2/transport/frame_data.c \
     src/core/ext/transport/chttp2/transport/frame_goaway.c \
     src/core/ext/transport/chttp2/transport/frame_ping.c \
@@ -263,6 +265,7 @@
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/tsi/fake_transport_security.c \
+    src/core/tsi/gts_transport_security.c \
     src/core/tsi/ssl_transport_security.c \
     src/core/tsi/transport_security.c \
     src/core/tsi/transport_security_adapter.c \
@@ -294,6 +297,8 @@
     src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
+    src/core/ext/transport/inproc/inproc_plugin.c \
+    src/core/ext/transport/inproc/inproc_transport.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \
     src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \
@@ -673,6 +678,7 @@
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/inproc)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug)
diff --git a/config.w32 b/config.w32
index a1f6d03..8529bd5 100644
--- a/config.w32
+++ b/config.w32
@@ -72,6 +72,7 @@
     "src\\core\\lib\\channel\\handshaker_registry.c " +
     "src\\core\\lib\\compression\\compression.c " +
     "src\\core\\lib\\compression\\message_compress.c " +
+    "src\\core\\lib\\compression\\stream_compression.c " +
     "src\\core\\lib\\http\\format_request.c " +
     "src\\core\\lib\\http\\httpcli.c " +
     "src\\core\\lib\\http\\parser.c " +
@@ -193,6 +194,7 @@
     "src\\core\\ext\\transport\\chttp2\\transport\\bin_encoder.c " +
     "src\\core\\ext\\transport\\chttp2\\transport\\chttp2_plugin.c " +
     "src\\core\\ext\\transport\\chttp2\\transport\\chttp2_transport.c " +
+    "src\\core\\ext\\transport\\chttp2\\transport\\flow_control.c " +
     "src\\core\\ext\\transport\\chttp2\\transport\\frame_data.c " +
     "src\\core\\ext\\transport\\chttp2\\transport\\frame_goaway.c " +
     "src\\core\\ext\\transport\\chttp2\\transport\\frame_ping.c " +
@@ -240,6 +242,7 @@
     "src\\core\\lib\\security\\util\\json_util.c " +
     "src\\core\\lib\\surface\\init_secure.c " +
     "src\\core\\tsi\\fake_transport_security.c " +
+    "src\\core\\tsi\\gts_transport_security.c " +
     "src\\core\\tsi\\ssl_transport_security.c " +
     "src\\core\\tsi\\transport_security.c " +
     "src\\core\\tsi\\transport_security_adapter.c " +
@@ -271,6 +274,8 @@
     "src\\core\\ext\\transport\\chttp2\\server\\insecure\\server_chttp2_posix.c " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.c " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.c " +
+    "src\\core\\ext\\transport\\inproc\\inproc_plugin.c " +
+    "src\\core\\ext\\transport\\inproc\\inproc_transport.c " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\client_load_reporting_filter.c " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb.c " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_channel_secure.c " +
@@ -685,6 +690,7 @@
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\server\\insecure");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\server\\secure");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\transport");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\inproc");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\channel");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\compression");
diff --git a/doc/environment_variables.md b/doc/environment_variables.md
index 339b705..036824d 100644
--- a/doc/environment_variables.md
+++ b/doc/environment_variables.md
@@ -5,8 +5,7 @@
 some configuration as environment variables that can be set.
 
 * http_proxy
-  The URI of the proxy to use for HTTP CONNECT support.  Does not currently
-  support username or password information in the URI.
+  The URI of the proxy to use for HTTP CONNECT support.
 
 * GRPC_ABORT_ON_LEAKS
   A debugging aid to cause a call to abort() when gRPC objects are leaked past
@@ -50,18 +49,23 @@
   - channel_stack_builder - traces information about channel stacks being built
   - http - traces state in the http2 transport engine
   - http1 - traces HTTP/1.x operations performed by gRPC
+  - inproc - traces the in-process transport
   - flowctl - traces http2 flow control
   - op_failure - traces error information when failure is pushed onto a
     completion queue
   - round_robin - traces the round_robin load balancing policy
+  - pick_first - traces the pick first load balancing policy
+  - resource_quota - trace resource quota objects internals
   - glb - traces the grpclb load balancer
   - queue_pluck
   - queue_timeout
   - server_channel - lightweight trace of significant server channel events
   - secure_endpoint - traces bytes flowing through encrypted channels
   - timer - timers (alarms) in the grpc internals
+  - timer_check - more detailed trace of timer logic in grpc internals
   - transport_security - traces metadata about secure channel establishment
   - tcp - traces bytes in and out of a channel
+  - tsi - traces tsi transport security
 
   The following tracers will only run in binaries built in DEBUG mode. This is
   accomplished by invoking `CONFIG=dbg make <target>`
@@ -74,6 +78,7 @@
   - stream_refcount
   - workqueue_refcount
   - fd_refcount
+  - cq_refcount
   - auth_context_refcount
   - security_connector_refcount
   - resolver_refcount
@@ -83,6 +88,11 @@
   'all' can additionally be used to turn all traces on.
   Individual traces can be disabled by prefixing them with '-'.
 
+  'refcount' will turn on all of the tracers for refcount debugging.
+
+  if 'list_tracers' is present, then all of the available tracers will be
+  printed when the program starts up.
+
   Example:
   export GRPC_TRACE=all,-pending_tags
 
@@ -92,6 +102,9 @@
   - INFO - log INFO and ERROR message
   - ERROR - log only errors
 
+* GRPC_TRACE_FUZZER
+  if set, the fuzzers will output trace (it is usually supressed).
+
 * GRPC_DNS_RESOLVER
   Declares which DNS resolver to use. The default is ares if gRPC is built with
   c-ares support. Otherwise, the value of this environment variable is ignored.
diff --git a/examples/BUILD b/examples/BUILD
index f38c1d9..3e9e508 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+licenses(["notice"])  # 3-clause BSD
+
 package(default_visibility = ["//visibility:public"])
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 3f841d5..11422f5 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -139,17 +139,6 @@
                       '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/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/impl/codegen/byte_buffer_reader.h',
                       'include/grpc/impl/codegen/compression_types.h',
                       'include/grpc/impl/codegen/connectivity_state.h',
@@ -170,13 +159,24 @@
                       'include/grpc/impl/codegen/sync_posix.h',
                       'include/grpc/impl/codegen/sync_windows.h',
                       'include/grpc/grpc_security.h',
+                      'include/grpc/byte_buffer.h',
+                      'include/grpc/byte_buffer_reader.h',
+                      'include/grpc/compression.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/census.h'
   end
   s.subspec 'Implementation' do |ss|
     ss.header_mappings_dir = '.'
     ss.libraries = 'z'
     ss.dependency "#{s.name}/Interface", version
-    ss.dependency 'BoringSSL', '~> 8.0'
+    ss.dependency 'BoringSSL', '~> 9.0'
     ss.dependency 'nanopb', '~> 0.3'
 
     # To save you from scrolling, this is the last part of the podspec.
@@ -244,6 +244,77 @@
                       'src/core/lib/support/tmpfile_posix.c',
                       'src/core/lib/support/tmpfile_windows.c',
                       'src/core/lib/support/wrap_memcpy.c',
+                      '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/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/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/transport/auth_filters.h',
+                      'src/core/lib/security/transport/lb_targets_info.h',
+                      'src/core/lib/security/transport/secure_endpoint.h',
+                      'src/core/lib/security/transport/security_connector.h',
+                      'src/core/lib/security/transport/security_handshaker.h',
+                      'src/core/lib/security/transport/tsi_error.h',
+                      'src/core/lib/security/util/json_util.h',
+                      'src/core/tsi/fake_transport_security.h',
+                      'src/core/tsi/gts_transport_security.h',
+                      'src/core/tsi/ssl_transport_security.h',
+                      'src/core/tsi/ssl_types.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/server/chttp2_server.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/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/deadline/deadline_filter.h',
+                      'src/core/ext/transport/chttp2/client/chttp2_connector.h',
+                      'src/core/ext/transport/inproc/inproc_transport.h',
                       'src/core/lib/channel/channel_args.h',
                       'src/core/lib/channel/channel_stack.h',
                       'src/core/lib/channel/channel_stack_builder.h',
@@ -254,6 +325,7 @@
                       'src/core/lib/channel/handshaker_registry.h',
                       'src/core/lib/compression/algorithm_metadata.h',
                       'src/core/lib/compression/message_compress.h',
+                      'src/core/lib/compression/stream_compression.h',
                       'src/core/lib/http/format_request.h',
                       'src/core/lib/http/httpcli.h',
                       'src/core/lib/http/parser.h',
@@ -276,9 +348,11 @@
                       'src/core/lib/iomgr/iomgr.h',
                       'src/core/lib/iomgr/iomgr_internal.h',
                       'src/core/lib/iomgr/iomgr_posix.h',
+                      'src/core/lib/iomgr/iomgr_uv.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',
@@ -354,75 +428,6 @@
                       'src/core/lib/transport/transport.h',
                       'src/core/lib/transport/transport_impl.h',
                       'src/core/lib/debug/trace.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/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/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/transport/auth_filters.h',
-                      'src/core/lib/security/transport/lb_targets_info.h',
-                      'src/core/lib/security/transport/secure_endpoint.h',
-                      'src/core/lib/security/transport/security_connector.h',
-                      'src/core/lib/security/transport/security_handshaker.h',
-                      'src/core/lib/security/transport/tsi_error.h',
-                      'src/core/lib/security/util/json_util.h',
-                      'src/core/tsi/fake_transport_security.h',
-                      'src/core/tsi/ssl_transport_security.h',
-                      'src/core/tsi/ssl_types.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/server/chttp2_server.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/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/deadline/deadline_filter.h',
-                      'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       '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',
@@ -466,6 +471,7 @@
                       'src/core/lib/channel/handshaker_registry.c',
                       'src/core/lib/compression/compression.c',
                       'src/core/lib/compression/message_compress.c',
+                      'src/core/lib/compression/stream_compression.c',
                       'src/core/lib/http/format_request.c',
                       'src/core/lib/http/httpcli.c',
                       'src/core/lib/http/parser.c',
@@ -587,6 +593,7 @@
                       'src/core/ext/transport/chttp2/transport/bin_encoder.c',
                       'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
                       'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+                      'src/core/ext/transport/chttp2/transport/flow_control.c',
                       'src/core/ext/transport/chttp2/transport/frame_data.c',
                       'src/core/ext/transport/chttp2/transport/frame_goaway.c',
                       'src/core/ext/transport/chttp2/transport/frame_ping.c',
@@ -634,6 +641,7 @@
                       'src/core/lib/security/util/json_util.c',
                       'src/core/lib/surface/init_secure.c',
                       'src/core/tsi/fake_transport_security.c',
+                      'src/core/tsi/gts_transport_security.c',
                       'src/core/tsi/ssl_transport_security.c',
                       'src/core/tsi/transport_security.c',
                       'src/core/tsi/transport_security_adapter.c',
@@ -665,6 +673,8 @@
                       'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
+                      'src/core/ext/transport/inproc/inproc_plugin.c',
+                      'src/core/ext/transport/inproc/inproc_transport.c',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c',
@@ -721,6 +731,77 @@
                               'src/core/lib/support/thd_internal.h',
                               'src/core/lib/support/time_precise.h',
                               'src/core/lib/support/tmpfile.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/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/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/transport/auth_filters.h',
+                              'src/core/lib/security/transport/lb_targets_info.h',
+                              'src/core/lib/security/transport/secure_endpoint.h',
+                              'src/core/lib/security/transport/security_connector.h',
+                              'src/core/lib/security/transport/security_handshaker.h',
+                              'src/core/lib/security/transport/tsi_error.h',
+                              'src/core/lib/security/util/json_util.h',
+                              'src/core/tsi/fake_transport_security.h',
+                              'src/core/tsi/gts_transport_security.h',
+                              'src/core/tsi/ssl_transport_security.h',
+                              'src/core/tsi/ssl_types.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/server/chttp2_server.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/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/deadline/deadline_filter.h',
+                              'src/core/ext/transport/chttp2/client/chttp2_connector.h',
+                              'src/core/ext/transport/inproc/inproc_transport.h',
                               'src/core/lib/channel/channel_args.h',
                               'src/core/lib/channel/channel_stack.h',
                               'src/core/lib/channel/channel_stack_builder.h',
@@ -731,6 +812,7 @@
                               'src/core/lib/channel/handshaker_registry.h',
                               'src/core/lib/compression/algorithm_metadata.h',
                               'src/core/lib/compression/message_compress.h',
+                              'src/core/lib/compression/stream_compression.h',
                               'src/core/lib/http/format_request.h',
                               'src/core/lib/http/httpcli.h',
                               'src/core/lib/http/parser.h',
@@ -753,9 +835,11 @@
                               'src/core/lib/iomgr/iomgr.h',
                               'src/core/lib/iomgr/iomgr_internal.h',
                               'src/core/lib/iomgr/iomgr_posix.h',
+                              'src/core/lib/iomgr/iomgr_uv.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',
@@ -831,75 +915,6 @@
                               'src/core/lib/transport/transport.h',
                               'src/core/lib/transport/transport_impl.h',
                               'src/core/lib/debug/trace.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/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/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/transport/auth_filters.h',
-                              'src/core/lib/security/transport/lb_targets_info.h',
-                              'src/core/lib/security/transport/secure_endpoint.h',
-                              'src/core/lib/security/transport/security_connector.h',
-                              'src/core/lib/security/transport/security_handshaker.h',
-                              'src/core/lib/security/transport/tsi_error.h',
-                              'src/core/lib/security/util/json_util.h',
-                              'src/core/tsi/fake_transport_security.h',
-                              'src/core/tsi/ssl_transport_security.h',
-                              'src/core/tsi/ssl_types.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/server/chttp2_server.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/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/deadline/deadline_filter.h',
-                              'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               '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',
diff --git a/grpc.gemspec b/grpc.gemspec
index 663915b..a456667 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -144,17 +144,6 @@
   s.files += %w( src/core/lib/support/tmpfile_posix.c )
   s.files += %w( src/core/lib/support/tmpfile_windows.c )
   s.files += %w( src/core/lib/support/wrap_memcpy.c )
-  s.files += %w( include/grpc/byte_buffer.h )
-  s.files += %w( include/grpc/byte_buffer_reader.h )
-  s.files += %w( include/grpc/compression.h )
-  s.files += %w( include/grpc/grpc.h )
-  s.files += %w( include/grpc/grpc_posix.h )
-  s.files += %w( include/grpc/grpc_security_constants.h )
-  s.files += %w( include/grpc/load_reporting.h )
-  s.files += %w( include/grpc/slice.h )
-  s.files += %w( include/grpc/slice_buffer.h )
-  s.files += %w( include/grpc/status.h )
-  s.files += %w( include/grpc/support/workaround_list.h )
   s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h )
   s.files += %w( include/grpc/impl/codegen/compression_types.h )
   s.files += %w( include/grpc/impl/codegen/connectivity_state.h )
@@ -175,7 +164,89 @@
   s.files += %w( include/grpc/impl/codegen/sync_posix.h )
   s.files += %w( include/grpc/impl/codegen/sync_windows.h )
   s.files += %w( include/grpc/grpc_security.h )
+  s.files += %w( include/grpc/byte_buffer.h )
+  s.files += %w( include/grpc/byte_buffer_reader.h )
+  s.files += %w( include/grpc/compression.h )
+  s.files += %w( include/grpc/grpc.h )
+  s.files += %w( include/grpc/grpc_posix.h )
+  s.files += %w( include/grpc/grpc_security_constants.h )
+  s.files += %w( include/grpc/load_reporting.h )
+  s.files += %w( include/grpc/slice.h )
+  s.files += %w( include/grpc/slice_buffer.h )
+  s.files += %w( include/grpc/status.h )
+  s.files += %w( include/grpc/support/workaround_list.h )
   s.files += %w( include/grpc/census.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/varint.h )
+  s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
+  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/lib/security/context/security_context.h )
+  s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/credentials.h )
+  s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/json_token.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.h )
+  s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
+  s.files += %w( src/core/lib/security/transport/auth_filters.h )
+  s.files += %w( src/core/lib/security/transport/lb_targets_info.h )
+  s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
+  s.files += %w( src/core/lib/security/transport/security_connector.h )
+  s.files += %w( src/core/lib/security/transport/security_handshaker.h )
+  s.files += %w( src/core/lib/security/transport/tsi_error.h )
+  s.files += %w( src/core/lib/security/util/json_util.h )
+  s.files += %w( src/core/tsi/fake_transport_security.h )
+  s.files += %w( src/core/tsi/gts_transport_security.h )
+  s.files += %w( src/core/tsi/ssl_transport_security.h )
+  s.files += %w( src/core/tsi/ssl_types.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/server/chttp2_server.h )
+  s.files += %w( src/core/ext/filters/client_channel/client_channel.h )
+  s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
+  s.files += %w( src/core/ext/filters/client_channel/connector.h )
+  s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.h )
+  s.files += %w( src/core/ext/filters/client_channel/http_proxy.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
+  s.files += %w( src/core/ext/filters/client_channel/parse_address.h )
+  s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h )
+  s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
+  s.files += %w( src/core/ext/filters/client_channel/resolver.h )
+  s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h )
+  s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h )
+  s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
+  s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
+  s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h )
+  s.files += %w( src/core/ext/filters/client_channel/uri_parser.h )
+  s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
+  s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
+  s.files += %w( src/core/ext/transport/inproc/inproc_transport.h )
   s.files += %w( src/core/lib/channel/channel_args.h )
   s.files += %w( src/core/lib/channel/channel_stack.h )
   s.files += %w( src/core/lib/channel/channel_stack_builder.h )
@@ -186,6 +257,7 @@
   s.files += %w( src/core/lib/channel/handshaker_registry.h )
   s.files += %w( src/core/lib/compression/algorithm_metadata.h )
   s.files += %w( src/core/lib/compression/message_compress.h )
+  s.files += %w( src/core/lib/compression/stream_compression.h )
   s.files += %w( src/core/lib/http/format_request.h )
   s.files += %w( src/core/lib/http/httpcli.h )
   s.files += %w( src/core/lib/http/parser.h )
@@ -208,9 +280,11 @@
   s.files += %w( src/core/lib/iomgr/iomgr.h )
   s.files += %w( src/core/lib/iomgr/iomgr_internal.h )
   s.files += %w( src/core/lib/iomgr/iomgr_posix.h )
+  s.files += %w( src/core/lib/iomgr/iomgr_uv.h )
   s.files += %w( src/core/lib/iomgr/is_epollexclusive_available.h )
   s.files += %w( src/core/lib/iomgr/load_file.h )
   s.files += %w( src/core/lib/iomgr/lockfree_event.h )
+  s.files += %w( src/core/lib/iomgr/nameser.h )
   s.files += %w( src/core/lib/iomgr/network_status_tracker.h )
   s.files += %w( src/core/lib/iomgr/polling_entity.h )
   s.files += %w( src/core/lib/iomgr/pollset.h )
@@ -286,85 +360,12 @@
   s.files += %w( src/core/lib/transport/transport.h )
   s.files += %w( src/core/lib/transport/transport_impl.h )
   s.files += %w( src/core/lib/debug/trace.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/varint.h )
-  s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
-  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/lib/security/context/security_context.h )
-  s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/credentials.h )
-  s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/jwt/json_token.h )
-  s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.h )
-  s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
-  s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
-  s.files += %w( src/core/lib/security/transport/auth_filters.h )
-  s.files += %w( src/core/lib/security/transport/lb_targets_info.h )
-  s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
-  s.files += %w( src/core/lib/security/transport/security_connector.h )
-  s.files += %w( src/core/lib/security/transport/security_handshaker.h )
-  s.files += %w( src/core/lib/security/transport/tsi_error.h )
-  s.files += %w( src/core/lib/security/util/json_util.h )
-  s.files += %w( src/core/tsi/fake_transport_security.h )
-  s.files += %w( src/core/tsi/ssl_transport_security.h )
-  s.files += %w( src/core/tsi/ssl_types.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/server/chttp2_server.h )
-  s.files += %w( src/core/ext/filters/client_channel/client_channel.h )
-  s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
-  s.files += %w( src/core/ext/filters/client_channel/connector.h )
-  s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.h )
-  s.files += %w( src/core/ext/filters/client_channel/http_proxy.h )
-  s.files += %w( src/core/ext/filters/client_channel/lb_policy.h )
-  s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
-  s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
-  s.files += %w( src/core/ext/filters/client_channel/parse_address.h )
-  s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h )
-  s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
-  s.files += %w( src/core/ext/filters/client_channel/resolver.h )
-  s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h )
-  s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h )
-  s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
-  s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
-  s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h )
-  s.files += %w( src/core/ext/filters/client_channel/uri_parser.h )
-  s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
-  s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
-  s.files += %w( third_party/nanopb/pb.h )
-  s.files += %w( third_party/nanopb/pb_common.h )
-  s.files += %w( third_party/nanopb/pb_decode.h )
-  s.files += %w( third_party/nanopb/pb_encode.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h )
@@ -402,6 +403,7 @@
   s.files += %w( src/core/lib/channel/handshaker_registry.c )
   s.files += %w( src/core/lib/compression/compression.c )
   s.files += %w( src/core/lib/compression/message_compress.c )
+  s.files += %w( src/core/lib/compression/stream_compression.c )
   s.files += %w( src/core/lib/http/format_request.c )
   s.files += %w( src/core/lib/http/httpcli.c )
   s.files += %w( src/core/lib/http/parser.c )
@@ -523,6 +525,7 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_plugin.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.c )
+  s.files += %w( src/core/ext/transport/chttp2/transport/flow_control.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.c )
@@ -570,6 +573,7 @@
   s.files += %w( src/core/lib/security/util/json_util.c )
   s.files += %w( src/core/lib/surface/init_secure.c )
   s.files += %w( src/core/tsi/fake_transport_security.c )
+  s.files += %w( src/core/tsi/gts_transport_security.c )
   s.files += %w( src/core/tsi/ssl_transport_security.c )
   s.files += %w( src/core/tsi/transport_security.c )
   s.files += %w( src/core/tsi/transport_security_adapter.c )
@@ -601,6 +605,8 @@
   s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c )
+  s.files += %w( src/core/ext/transport/inproc/inproc_plugin.c )
+  s.files += %w( src/core/ext/transport/inproc/inproc_transport.c )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c )
diff --git a/include/grpc++/alarm.h b/include/grpc++/alarm.h
index 00a9306..ed8dacb 100644
--- a/include/grpc++/alarm.h
+++ b/include/grpc++/alarm.h
@@ -77,7 +77,7 @@
   void Cancel() { grpc_alarm_cancel(alarm_); }
 
  private:
-  class AlarmEntry : public internal::CompletionQueueTag {
+  class AlarmEntry : public CompletionQueueTag {
    public:
     AlarmEntry(void* tag) : tag_(tag) {}
     bool FinalizeResult(void** tag, bool* status) override {
diff --git a/include/grpc++/channel.h b/include/grpc++/channel.h
index 5ba3c59..c50091d 100644
--- a/include/grpc++/channel.h
+++ b/include/grpc++/channel.h
@@ -32,7 +32,7 @@
 namespace grpc {
 /// Channels represent a connection to an endpoint. Created by \a CreateChannel.
 class Channel final : public ChannelInterface,
-                      public internal::CallHook,
+                      public CallHook,
                       public std::enable_shared_from_this<Channel>,
                       private GrpcLibraryCodegen {
  public:
@@ -52,7 +52,7 @@
  private:
   template <class InputMessage, class OutputMessage>
   friend Status BlockingUnaryCall(ChannelInterface* channel,
-                                  const internal::RpcMethod& method,
+                                  const RpcMethod& method,
                                   ClientContext* context,
                                   const InputMessage& request,
                                   OutputMessage* result);
@@ -60,11 +60,9 @@
       const grpc::string& host, grpc_channel* c_channel);
   Channel(const grpc::string& host, grpc_channel* c_channel);
 
-  internal::Call CreateCall(const internal::RpcMethod& method,
-                            ClientContext* context,
-                            CompletionQueue* cq) override;
-  void PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                        internal::Call* call) override;
+  Call CreateCall(const RpcMethod& method, ClientContext* context,
+                  CompletionQueue* cq) override;
+  void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override;
   void* RegisterMethod(const char* method) override;
 
   void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h
index ddbf3e6..9cf7ac3 100644
--- a/include/grpc++/impl/codegen/async_stream.h
+++ b/include/grpc++/impl/codegen/async_stream.h
@@ -30,7 +30,6 @@
 
 class CompletionQueue;
 
-namespace internal {
 /// Common interface for all client side asynchronous streaming.
 class ClientAsyncStreamingInterface {
  public:
@@ -147,41 +146,9 @@
   }
 };
 
-}  // namespace internal
-
 template <class R>
-class ClientAsyncReaderInterface
-    : public internal::ClientAsyncStreamingInterface,
-      public internal::AsyncReaderInterface<R> {};
-
-/// Common interface for client side asynchronous writing.
-template <class W>
-class ClientAsyncWriterInterface
-    : public internal::ClientAsyncStreamingInterface,
-      public internal::AsyncWriterInterface<W> {
- public:
-  /// Signal the client is done with the writes (half-close the client stream).
-  /// Thread-safe with respect to \a AsyncReaderInterface::Read
-  ///
-  /// \param[in] tag The tag identifying the operation.
-  virtual void WritesDone(void* tag) = 0;
-};
-
-/// Async client-side interface for bi-directional streaming,
-/// where the client-to-server message stream has messages of type \a W,
-/// and the server-to-client message stream has messages of type \a R.
-template <class W, class R>
-class ClientAsyncReaderWriterInterface
-    : public internal::ClientAsyncStreamingInterface,
-      public internal::AsyncWriterInterface<W>,
-      public internal::AsyncReaderInterface<R> {
- public:
-  /// Signal the client is done with the writes (half-close the client stream).
-  /// Thread-safe with respect to \a AsyncReaderInterface::Read
-  ///
-  /// \param[in] tag The tag identifying the operation.
-  virtual void WritesDone(void* tag) = 0;
-};
+class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
+                                   public AsyncReaderInterface<R> {};
 
 /// Async client-side API for doing server-streaming RPCs,
 /// where the incoming message stream coming from the server has
@@ -189,24 +156,21 @@
 template <class R>
 class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
  public:
-  struct internal {
-    /// Create a stream and write the first request out.
-    /// \a tag will be notified on \a cq when the call has been started and
-    /// \a request has been written out.
-    /// Note that \a context will be used to fill in custom initial metadata
-    /// used to send to the server when starting the call.
-    template <class W>
-    static ClientAsyncReader* Create(::grpc::ChannelInterface* channel,
-                                     CompletionQueue* cq,
-                                     const ::grpc::internal::RpcMethod& method,
-                                     ClientContext* context, const W& request,
-                                     void* tag) {
-      ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
-      return new (g_core_codegen_interface->grpc_call_arena_alloc(
-          call.call(), sizeof(ClientAsyncReader)))
-          ClientAsyncReader(call, context, request, tag);
-    }
-  };
+  /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started and
+  /// \a request has been written out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  template <class W>
+  static ClientAsyncReader* Create(ChannelInterface* channel,
+                                   CompletionQueue* cq, const RpcMethod& method,
+                                   ClientContext* context, const W& request,
+                                   void* tag) {
+    Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncReader)))
+        ClientAsyncReader(call, context, request, tag);
+  }
 
   // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
@@ -254,8 +218,8 @@
 
  private:
   template <class W>
-  ClientAsyncReader(::grpc::internal::Call call, ClientContext* context,
-                    const W& request, void* tag)
+  ClientAsyncReader(Call call, ClientContext* context, const W& request,
+                    void* tag)
       : context_(context), call_(call) {
     init_ops_.set_output_tag(tag);
     init_ops_.SendInitialMetadata(context->send_initial_metadata_,
@@ -267,19 +231,24 @@
   }
 
   ClientContext* context_;
-  ::grpc::internal::Call call_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpClientSendClose>
+  Call call_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
       init_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpRecvMessage<R>>
-      read_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpClientRecvStatus>
-      finish_ops_;
+  CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
+  CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
+  CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
+};
+
+/// Common interface for client side asynchronous writing.
+template <class W>
+class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
+                                   public AsyncWriterInterface<W> {
+ public:
+  /// Signal the client is done with the writes (half-close the client stream).
+  /// Thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WritesDone(void* tag) = 0;
 };
 
 /// Async API on the client side for doing client-streaming RPCs,
@@ -288,27 +257,24 @@
 template <class W>
 class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
  public:
-  struct internal {
-    /// Create a stream and write the first request out.
-    /// \a tag will be notified on \a cq when the call has been started (i.e.
-    /// intitial metadata sent) and \a request has been written out.
-    /// Note that \a context will be used to fill in custom initial metadata
-    /// used to send to the server when starting the call.
-    /// \a response will be filled in with the single expected response
-    /// message from the server upon a successful call to the \a Finish
-    /// method of this instance.
-    template <class R>
-    static ClientAsyncWriter* Create(::grpc::ChannelInterface* channel,
-                                     CompletionQueue* cq,
-                                     const ::grpc::internal::RpcMethod& method,
-                                     ClientContext* context, R* response,
-                                     void* tag) {
-      ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
-      return new (g_core_codegen_interface->grpc_call_arena_alloc(
-          call.call(), sizeof(ClientAsyncWriter)))
-          ClientAsyncWriter(call, context, response, tag);
-    }
-  };
+  /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent) and \a request has been written out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  /// \a response will be filled in with the single expected response
+  /// message from the server upon a successful call to the \a Finish
+  /// method of this instance.
+  template <class R>
+  static ClientAsyncWriter* Create(ChannelInterface* channel,
+                                   CompletionQueue* cq, const RpcMethod& method,
+                                   ClientContext* context, R* response,
+                                   void* tag) {
+    Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncWriter)))
+        ClientAsyncWriter(call, context, response, tag);
+  }
 
   // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
@@ -372,8 +338,7 @@
 
  private:
   template <class R>
-  ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context,
-                    R* response, void* tag)
+  ClientAsyncWriter(Call call, ClientContext* context, R* response, void* tag)
       : context_(context), call_(call) {
     finish_ops_.RecvMessage(response);
     finish_ops_.AllowNoMessage();
@@ -391,20 +356,31 @@
   }
 
   ClientContext* context_;
-  ::grpc::internal::Call call_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpClientSendClose>
+  Call call_;
+  CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
       write_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpGenericRecvMessage,
-                              ::grpc::internal::CallOpClientRecvStatus>
+  CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
+            CallOpClientRecvStatus>
       finish_ops_;
 };
 
 /// Async client-side interface for bi-directional streaming,
+/// where the client-to-server message stream has messages of type \a W,
+/// and the server-to-client message stream has messages of type \a R.
+template <class W, class R>
+class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
+                                         public AsyncWriterInterface<W>,
+                                         public AsyncReaderInterface<R> {
+ public:
+  /// Signal the client is done with the writes (half-close the client stream).
+  /// Thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WritesDone(void* tag) = 0;
+};
+
+/// Async client-side interface for bi-directional streaming,
 /// where the outgoing message stream going to the server
 /// has messages of type \a W,  and the incoming message stream coming
 /// from the server has messages of type \a R.
@@ -412,23 +388,21 @@
 class ClientAsyncReaderWriter final
     : public ClientAsyncReaderWriterInterface<W, R> {
  public:
-  struct internal {
-    /// Create a stream and write the first request out.
-    /// \a tag will be notified on \a cq when the call has been started (i.e.
-    /// intitial metadata sent).
-    /// Note that \a context will be used to fill in custom initial metadata
-    /// used to send to the server when starting the call.
-    static ClientAsyncReaderWriter* Create(
-        ::grpc::ChannelInterface* channel, CompletionQueue* cq,
-        const ::grpc::internal::RpcMethod& method, ClientContext* context,
-        void* tag) {
-      ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+  /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent).
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  static ClientAsyncReaderWriter* Create(ChannelInterface* channel,
+                                         CompletionQueue* cq,
+                                         const RpcMethod& method,
+                                         ClientContext* context, void* tag) {
+    Call call = channel->CreateCall(method, context, cq);
 
-      return new (g_core_codegen_interface->grpc_call_arena_alloc(
-          call.call(), sizeof(ClientAsyncReaderWriter)))
-          ClientAsyncReaderWriter(call, context, tag);
-    }
-  };
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncReaderWriter)))
+        ClientAsyncReaderWriter(call, context, tag);
+  }
 
   // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
@@ -497,8 +471,7 @@
   }
 
  private:
-  ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context,
-                          void* tag)
+  ClientAsyncReaderWriter(Call call, ClientContext* context, void* tag)
       : context_(context), call_(call) {
     if (context_->initial_metadata_corked_) {
       // if corked bit is set in context, we buffer up the initial metadata to
@@ -514,25 +487,17 @@
   }
 
   ClientContext* context_;
-  ::grpc::internal::Call call_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpRecvMessage<R>>
-      read_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpClientSendClose>
+  Call call_;
+  CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
+  CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
       write_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpClientRecvStatus>
-      finish_ops_;
+  CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
 };
 
 template <class W, class R>
-class ServerAsyncReaderInterface
-    : public internal::ServerAsyncStreamingInterface,
-      public internal::AsyncReaderInterface<R> {
+class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface,
+                                   public AsyncReaderInterface<R> {
  public:
   /// Indicate that the stream is to be finished with a certain status code
   /// and also send out \a msg response to the client.
@@ -576,89 +541,6 @@
   virtual void FinishWithError(const Status& status, void* tag) = 0;
 };
 
-template <class W>
-class ServerAsyncWriterInterface
-    : public internal::ServerAsyncStreamingInterface,
-      public internal::AsyncWriterInterface<W> {
- public:
-  /// Indicate that the stream is to be finished with a certain status code.
-  /// Request notification for when the server has sent the appropriate
-  /// signals to the client to end the call.
-  /// Should not be used concurrently with other operations.
-  ///
-  /// It is appropriate to call this method when either:
-  ///   * all messages from the client have been received (either known
-  ///     implictly, or explicitly because a previous \a
-  ///     AsyncReaderInterface::Read operation with a non-ok
-  ///     result (e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
-  ///   * it is desired to end the call early with some non-OK status code.
-  ///
-  /// This operation will end when the server has finished sending out initial
-  /// metadata (if not sent already), response message, and status, or if
-  /// some failure occurred when trying to do so.
-  ///
-  /// \param[in] tag Tag identifying this request.
-  /// \param[in] status To be sent to the client as the result of this call.
-  virtual void Finish(const Status& status, void* tag) = 0;
-
-  /// Request the writing of \a msg and coalesce it with trailing metadata which
-  /// contains \a status, using WriteOptions options with
-  /// identifying tag \a tag.
-  ///
-  /// WriteAndFinish is equivalent of performing WriteLast and Finish
-  /// in a single step.
-  ///
-  /// \param[in] msg The message to be written.
-  /// \param[in] options The WriteOptions to be used to write this message.
-  /// \param[in] status The Status that server returns to client.
-  /// \param[in] tag The tag identifying the operation.
-  virtual void WriteAndFinish(const W& msg, WriteOptions options,
-                              const Status& status, void* tag) = 0;
-};
-
-/// Server-side interface for asynchronous bi-directional streaming.
-template <class W, class R>
-class ServerAsyncReaderWriterInterface
-    : public internal::ServerAsyncStreamingInterface,
-      public internal::AsyncWriterInterface<W>,
-      public internal::AsyncReaderInterface<R> {
- public:
-  /// Indicate that the stream is to be finished with a certain status code.
-  /// Request notification for when the server has sent the appropriate
-  /// signals to the client to end the call.
-  /// Should not be used concurrently with other operations.
-  ///
-  /// It is appropriate to call this method when either:
-  ///   * all messages from the client have been received (either known
-  ///     implictly, or explicitly because a previous \a
-  ///     AsyncReaderInterface::Read operation
-  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
-  ///     with 'false'.
-  ///   * it is desired to end the call early with some non-OK status code.
-  ///
-  /// This operation will end when the server has finished sending out initial
-  /// metadata (if not sent already), response message, and status, or if some
-  /// failure occurred when trying to do so.
-  ///
-  /// \param[in] tag Tag identifying this request.
-  /// \param[in] status To be sent to the client as the result of this call.
-  virtual void Finish(const Status& status, void* tag) = 0;
-
-  /// Request the writing of \a msg and coalesce it with trailing metadata which
-  /// contains \a status, using WriteOptions options with
-  /// identifying tag \a tag.
-  ///
-  /// WriteAndFinish is equivalent of performing WriteLast and Finish in a
-  /// single step.
-  ///
-  /// \param[in] msg The message to be written.
-  /// \param[in] options The WriteOptions to be used to write this message.
-  /// \param[in] status The Status that server returns to client.
-  /// \param[in] tag The tag identifying the operation.
-  virtual void WriteAndFinish(const W& msg, WriteOptions options,
-                              const Status& status, void* tag) = 0;
-};
-
 /// Async server-side API for doing client-streaming RPCs,
 /// where the incoming message stream from the client has messages of type \a R,
 /// and the single response message sent from the server is type \a W.
@@ -742,19 +624,56 @@
   }
 
  private:
-  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+  void BindCall(Call* call) override { call_ = *call; }
 
-  ::grpc::internal::Call call_;
+  Call call_;
   ServerContext* ctx_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpServerSendStatus>
+  CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+  CallOpSet<CallOpRecvMessage<R>> read_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+            CallOpServerSendStatus>
       finish_ops_;
 };
 
+template <class W>
+class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
+                                   public AsyncWriterInterface<W> {
+ public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a
+  ///     AsyncReaderInterface::Read operation with a non-ok
+  ///     result (e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), response message, and status, or if
+  /// some failure occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  virtual void Finish(const Status& status, void* tag) = 0;
+
+  /// Request the writing of \a msg and coalesce it with trailing metadata which
+  /// contains \a status, using WriteOptions options with
+  /// identifying tag \a tag.
+  ///
+  /// WriteAndFinish is equivalent of performing WriteLast and Finish
+  /// in a single step.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] status The Status that server returns to client.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WriteAndFinish(const W& msg, WriteOptions options,
+                              const Status& status, void* tag) = 0;
+};
+
 /// Async server-side API for doing server streaming RPCs,
 /// where the outgoing message stream from the server has messages of type \a W.
 template <class W>
@@ -836,7 +755,7 @@
   }
 
  private:
-  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+  void BindCall(Call* call) override { call_ = *call; }
 
   template <class T>
   void EnsureInitialMetadataSent(T* ops) {
@@ -850,17 +769,55 @@
     }
   }
 
-  ::grpc::internal::Call call_;
+  Call call_;
   ServerContext* ctx_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpServerSendStatus>
+  CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+            CallOpServerSendStatus>
       write_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpServerSendStatus>
-      finish_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
+};
+
+/// Server-side interface for asynchronous bi-directional streaming.
+template <class W, class R>
+class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface,
+                                         public AsyncWriterInterface<W>,
+                                         public AsyncReaderInterface<R> {
+ public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a
+  ///     AsyncReaderInterface::Read operation
+  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+  ///     with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), response message, and status, or if some
+  /// failure occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  virtual void Finish(const Status& status, void* tag) = 0;
+
+  /// Request the writing of \a msg and coalesce it with trailing metadata which
+  /// contains \a status, using WriteOptions options with
+  /// identifying tag \a tag.
+  ///
+  /// WriteAndFinish is equivalent of performing WriteLast and Finish in a
+  /// single step.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] status The Status that server returns to client.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WriteAndFinish(const W& msg, WriteOptions options,
+                              const Status& status, void* tag) = 0;
 };
 
 /// Async server-side API for doing bidirectional streaming RPCs,
@@ -955,7 +912,7 @@
  private:
   friend class ::grpc::Server;
 
-  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+  void BindCall(Call* call) override { call_ = *call; }
 
   template <class T>
   void EnsureInitialMetadataSent(T* ops) {
@@ -969,18 +926,14 @@
     }
   }
 
-  ::grpc::internal::Call call_;
+  Call call_;
   ServerContext* ctx_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-      meta_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpServerSendStatus>
+  CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+  CallOpSet<CallOpRecvMessage<R>> read_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+            CallOpServerSendStatus>
       write_ops_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpServerSendStatus>
-      finish_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index 45a8e8e..41b3ae3 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -75,18 +75,17 @@
   /// intitial metadata sent) and \a request has been written out.
   /// Note that \a context will be used to fill in custom initial metadata
   /// used to send to the server when starting the call.
-  struct internal {
-    template <class W>
-    static ClientAsyncResponseReader* Create(
-        ::grpc::ChannelInterface* channel, CompletionQueue* cq,
-        const ::grpc::internal::RpcMethod& method, ClientContext* context,
-        const W& request) {
-      ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
-      return new (g_core_codegen_interface->grpc_call_arena_alloc(
-          call.call(), sizeof(ClientAsyncResponseReader)))
-          ClientAsyncResponseReader(call, context, request);
-    }
-  };
+  template <class W>
+  static ClientAsyncResponseReader* Create(ChannelInterface* channel,
+                                           CompletionQueue* cq,
+                                           const RpcMethod& method,
+                                           ClientContext* context,
+                                           const W& request) {
+    Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncResponseReader)))
+        ClientAsyncResponseReader(call, context, request);
+  }
 
   /// TODO(vjpai): Delete the below constructor
   /// PLEASE DO NOT USE THIS CONSTRUCTOR IN NEW CODE
@@ -95,10 +94,9 @@
   /// created this struct rather than properly using a stub.
   /// This code will not remain a valid public constructor for long.
   template <class W>
-  ClientAsyncResponseReader(::grpc::ChannelInterface* channel,
-                            CompletionQueue* cq,
-                            const ::grpc::internal::RpcMethod& method,
-                            ClientContext* context, const W& request)
+  ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
+                            const RpcMethod& method, ClientContext* context,
+                            const W& request)
       : context_(context),
         call_(channel->CreateCall(method, context, cq)),
         collection_(std::make_shared<Ops>()) {
@@ -166,11 +164,10 @@
 
  private:
   ClientContext* const context_;
-  ::grpc::internal::Call call_;
+  Call call_;
 
   template <class W>
-  ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context,
-                            const W& request)
+  ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
       : context_(context), call_(call) {
     ops_.init_buf.SendInitialMetadata(context->send_initial_metadata_,
                                       context->initial_metadata_flags());
@@ -186,17 +183,13 @@
 
   // TODO(vjpai): Remove the reference to CallOpSetCollectionInterface
   // as soon as the related workaround (public constructor) is deleted
-  struct Ops : public ::grpc::internal::CallOpSetCollectionInterface {
-    ::grpc::internal::SneakyCallOpSet<
-        ::grpc::internal::CallOpSendInitialMetadata,
-        ::grpc::internal::CallOpSendMessage,
-        ::grpc::internal::CallOpClientSendClose>
+  struct Ops : public CallOpSetCollectionInterface {
+    SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+                    CallOpClientSendClose>
         init_buf;
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-        meta_buf;
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                                ::grpc::internal::CallOpRecvMessage<R>,
-                                ::grpc::internal::CallOpClientRecvStatus>
+    CallOpSet<CallOpRecvInitialMetadata> meta_buf;
+    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
+              CallOpClientRecvStatus>
         finish_buf;
   } ops_;
 
@@ -208,8 +201,7 @@
 /// Async server-side API for handling unary calls, where the single
 /// response message sent to the client is of type \a W.
 template <class W>
-class ServerAsyncResponseWriter final
-    : public internal::ServerAsyncStreamingInterface {
+class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
  public:
   explicit ServerAsyncResponseWriter(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
@@ -297,15 +289,13 @@
   }
 
  private:
-  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+  void BindCall(Call* call) override { call_ = *call; }
 
-  ::grpc::internal::Call call_;
+  Call call_;
   ServerContext* ctx_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-      meta_buf_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                              ::grpc::internal::CallOpSendMessage,
-                              ::grpc::internal::CallOpServerSendStatus>
+  CallOpSet<CallOpSendInitialMetadata> meta_buf_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+            CallOpServerSendStatus>
       finish_buf_;
 };
 
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 9bbe7c6..f6eefb9 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -44,12 +44,10 @@
 namespace grpc {
 
 class ByteBuffer;
-class CompletionQueue;
-extern CoreCodegenInterface* g_core_codegen_interface;
-
-namespace internal {
 class Call;
 class CallHook;
+class CompletionQueue;
+extern CoreCodegenInterface* g_core_codegen_interface;
 
 const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin";
 
@@ -78,7 +76,6 @@
   }
   return metadata_array;
 }
-}  // namespace internal
 
 /// Per-message write options.
 class WriteOptions {
@@ -194,7 +191,6 @@
   bool last_message_;
 };
 
-namespace internal {
 /// Default argument for CallOpSet. I is unused by the class, but can be
 /// used for generating multiple names for the same thing.
 template <int I>
@@ -682,7 +678,7 @@
   grpc_call* call_;
   int max_receive_message_size_;
 };
-}  // namespace internal
+
 }  // namespace grpc
 
 #endif  // GRPCXX_IMPL_CODEGEN_CALL_H
diff --git a/include/grpc++/impl/codegen/call_hook.h b/include/grpc++/impl/codegen/call_hook.h
index 44e9de2..d026cc8 100644
--- a/include/grpc++/impl/codegen/call_hook.h
+++ b/include/grpc++/impl/codegen/call_hook.h
@@ -21,7 +21,6 @@
 
 namespace grpc {
 
-namespace internal {
 class CallOpSetInterface;
 class Call;
 
@@ -32,7 +31,6 @@
   virtual ~CallHook() {}
   virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
 };
-}  // namespace internal
 
 }  // namespace grpc
 
diff --git a/include/grpc++/impl/codegen/channel_interface.h b/include/grpc++/impl/codegen/channel_interface.h
index cf1d77e..1b7590b 100644
--- a/include/grpc++/impl/codegen/channel_interface.h
+++ b/include/grpc++/impl/codegen/channel_interface.h
@@ -24,8 +24,10 @@
 #include <grpc/impl/codegen/connectivity_state.h>
 
 namespace grpc {
-class ChannelInterface;
+class Call;
 class ClientContext;
+class RpcMethod;
+class CallOpSetInterface;
 class CompletionQueue;
 
 template <class R>
@@ -43,16 +45,6 @@
 template <class R>
 class ClientAsyncResponseReader;
 
-namespace internal {
-class Call;
-class CallOpSetInterface;
-class RpcMethod;
-template <class InputMessage, class OutputMessage>
-Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
-                         ClientContext* context, const InputMessage& request,
-                         OutputMessage* result);
-}  // namespace internal
-
 /// Codegen interface for \a grpc::Channel.
 class ChannelInterface {
  public:
@@ -104,16 +96,15 @@
   template <class R>
   friend class ::grpc::ClientAsyncResponseReader;
   template <class InputMessage, class OutputMessage>
-  friend Status(::grpc::internal::BlockingUnaryCall)(
-      ChannelInterface* channel, const internal::RpcMethod& method,
-      ClientContext* context, const InputMessage& request,
-      OutputMessage* result);
-  friend class ::grpc::internal::RpcMethod;
-  virtual internal::Call CreateCall(const internal::RpcMethod& method,
-                                    ClientContext* context,
-                                    CompletionQueue* cq) = 0;
-  virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                                internal::Call* call) = 0;
+  friend Status BlockingUnaryCall(ChannelInterface* channel,
+                                  const RpcMethod& method,
+                                  ClientContext* context,
+                                  const InputMessage& request,
+                                  OutputMessage* result);
+  friend class ::grpc::RpcMethod;
+  virtual Call CreateCall(const RpcMethod& method, ClientContext* context,
+                          CompletionQueue* cq) = 0;
+  virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
   virtual void* RegisterMethod(const char* method) = 0;
   virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
                                        gpr_timespec deadline,
@@ -121,6 +112,7 @@
   virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
                                       gpr_timespec deadline) = 0;
 };
+
 }  // namespace grpc
 
 #endif  // GRPCXX_IMPL_CODEGEN_CHANNEL_INTERFACE_H
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index 89eb8b9..6d7e13b 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -60,18 +60,7 @@
 class ChannelInterface;
 class CompletionQueue;
 class CallCredentials;
-class ClientContext;
-
-namespace internal {
 class RpcMethod;
-class CallOpClientRecvStatus;
-class CallOpRecvInitialMetadata;
-template <class InputMessage, class OutputMessage>
-Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
-                         ClientContext* context, const InputMessage& request,
-                         OutputMessage* result);
-}  // namespace internal
-
 template <class R>
 class ClientReader;
 template <class W>
@@ -356,8 +345,8 @@
   ClientContext& operator=(const ClientContext&);
 
   friend class ::grpc::testing::InteropClientContextInspector;
-  friend class ::grpc::internal::CallOpClientRecvStatus;
-  friend class ::grpc::internal::CallOpRecvInitialMetadata;
+  friend class CallOpClientRecvStatus;
+  friend class CallOpRecvInitialMetadata;
   friend class Channel;
   template <class R>
   friend class ::grpc::ClientReader;
@@ -374,10 +363,11 @@
   template <class R>
   friend class ::grpc::ClientAsyncResponseReader;
   template <class InputMessage, class OutputMessage>
-  friend Status(::grpc::internal::BlockingUnaryCall)(
-      ChannelInterface* channel, const internal::RpcMethod& method,
-      ClientContext* context, const InputMessage& request,
-      OutputMessage* result);
+  friend Status BlockingUnaryCall(ChannelInterface* channel,
+                                  const RpcMethod& method,
+                                  ClientContext* context,
+                                  const InputMessage& request,
+                                  OutputMessage* result);
 
   grpc_call* call() const { return call_; }
   void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
@@ -409,8 +399,8 @@
   mutable std::shared_ptr<const AuthContext> auth_context_;
   struct census_context* census_context_;
   std::multimap<grpc::string, grpc::string> send_initial_metadata_;
-  internal::MetadataMap recv_initial_metadata_;
-  internal::MetadataMap trailing_metadata_;
+  MetadataMap recv_initial_metadata_;
+  MetadataMap trailing_metadata_;
 
   grpc_call* propagate_from_call_;
   PropagationOptions propagation_options_;
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index 8fef3ab..7c540fa 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -30,9 +30,8 @@
 class Channel;
 class ClientContext;
 class CompletionQueue;
-
-namespace internal {
 class RpcMethod;
+
 /// Wrapper that performs a blocking unary call
 template <class InputMessage, class OutputMessage>
 Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
@@ -68,7 +67,6 @@
   return status;
 }
 
-}  // namespace internal
 }  // namespace grpc
 
 #endif  // GRPCXX_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h
index a04778a..ca757e2 100644
--- a/include/grpc++/impl/codegen/completion_queue.h
+++ b/include/grpc++/impl/codegen/completion_queue.h
@@ -56,19 +56,7 @@
 namespace internal {
 template <class W, class R>
 class ServerReaderWriterBody;
-}  // namespace internal
-
-class Channel;
-class ChannelInterface;
-class ClientContext;
-class CompletionQueue;
-class Server;
-class ServerBuilder;
-class ServerContext;
-
-namespace internal {
-class CompletionQueueTag;
-class RpcMethod;
+}
 template <class ServiceType, class RequestType, class ResponseType>
 class RpcMethodHandler;
 template <class ServiceType, class RequestType, class ResponseType>
@@ -78,13 +66,16 @@
 template <class ServiceType, class RequestType, class ResponseType>
 class BidiStreamingHandler;
 class UnknownMethodHandler;
-template <class Streamer, bool WriteNeeded>
-class TemplatedBidiStreamingHandler;
-template <class InputMessage, class OutputMessage>
-Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
-                         ClientContext* context, const InputMessage& request,
-                         OutputMessage* result);
-}  // namespace internal
+
+class Channel;
+class ChannelInterface;
+class ClientContext;
+class CompletionQueueTag;
+class CompletionQueue;
+class RpcMethod;
+class Server;
+class ServerBuilder;
+class ServerContext;
 
 extern CoreCodegenInterface* g_core_codegen_interface;
 
@@ -205,27 +196,28 @@
   template <class W, class R>
   friend class ::grpc::internal::ServerReaderWriterBody;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::RpcMethodHandler;
+  friend class RpcMethodHandler;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::ClientStreamingHandler;
+  friend class ClientStreamingHandler;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::ServerStreamingHandler;
+  friend class ServerStreamingHandler;
   template <class Streamer, bool WriteNeeded>
-  friend class ::grpc::internal::TemplatedBidiStreamingHandler;
-  friend class ::grpc::internal::UnknownMethodHandler;
+  friend class TemplatedBidiStreamingHandler;
+  friend class UnknownMethodHandler;
   friend class ::grpc::Server;
   friend class ::grpc::ServerContext;
   template <class InputMessage, class OutputMessage>
-  friend Status(::grpc::internal::BlockingUnaryCall)(
-      ChannelInterface* channel, const internal::RpcMethod& method,
-      ClientContext* context, const InputMessage& request,
-      OutputMessage* result);
+  friend Status BlockingUnaryCall(ChannelInterface* channel,
+                                  const RpcMethod& method,
+                                  ClientContext* context,
+                                  const InputMessage& request,
+                                  OutputMessage* result);
 
   NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
 
   /// Wraps \a grpc_completion_queue_pluck.
   /// \warning Must not be mixed with calls to \a Next.
-  bool Pluck(internal::CompletionQueueTag* tag) {
+  bool Pluck(CompletionQueueTag* tag) {
     auto deadline =
         g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
     auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
@@ -246,7 +238,7 @@
   /// implementation to simple call the other TryPluck function with a zero
   /// timeout. i.e:
   ///      TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME))
-  void TryPluck(internal::CompletionQueueTag* tag) {
+  void TryPluck(CompletionQueueTag* tag) {
     auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME);
     auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
         cq_, tag, deadline, nullptr);
@@ -262,7 +254,7 @@
   ///
   /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects
   /// that the tag is internal not something that is returned to the user.
-  void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) {
+  void TryPluck(CompletionQueueTag* tag, gpr_timespec deadline) {
     auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
         cq_, tag, deadline, nullptr);
     if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) {
diff --git a/include/grpc++/impl/codegen/completion_queue_tag.h b/include/grpc++/impl/codegen/completion_queue_tag.h
index cb16bcf..4d7d3a9 100644
--- a/include/grpc++/impl/codegen/completion_queue_tag.h
+++ b/include/grpc++/impl/codegen/completion_queue_tag.h
@@ -21,7 +21,6 @@
 
 namespace grpc {
 
-namespace internal {
 /// An interface allowing implementors to process and filter event tags.
 class CompletionQueueTag {
  public:
@@ -32,7 +31,6 @@
   /// queue
   virtual bool FinalizeResult(void** tag, bool* status) = 0;
 };
-}  // namespace internal
 
 }  // namespace grpc
 
diff --git a/include/grpc++/impl/codegen/config_protobuf.h b/include/grpc++/impl/codegen/config_protobuf.h
index 7387fa2..c5e5bdf 100644
--- a/include/grpc++/impl/codegen/config_protobuf.h
+++ b/include/grpc++/impl/codegen/config_protobuf.h
@@ -19,8 +19,6 @@
 #ifndef GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H
 #define GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H
 
-#define GRPC_OPEN_SOURCE_PROTO
-
 #ifndef GRPC_CUSTOM_PROTOBUF_INT64
 #include <google/protobuf/stubs/common.h>
 #define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64
diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h
index 504c79c..2b15a01 100644
--- a/include/grpc++/impl/codegen/core_codegen.h
+++ b/include/grpc++/impl/codegen/core_codegen.h
@@ -60,6 +60,10 @@
   void gpr_cv_signal(gpr_cv* cv) override;
   void gpr_cv_broadcast(gpr_cv* cv) override;
 
+  grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+                                               grpc_status_code status,
+                                               const char* description,
+                                               void* reserved) override;
   void grpc_call_ref(grpc_call* call) override;
   void grpc_call_unref(grpc_call* call) override;
   virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h
index 930b116..b4c771a 100644
--- a/include/grpc++/impl/codegen/core_codegen_interface.h
+++ b/include/grpc++/impl/codegen/core_codegen_interface.h
@@ -89,6 +89,10 @@
   virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
                                                    void (*destroy)(void*),
                                                    void* user_data) = 0;
+  virtual grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+                                                       grpc_status_code status,
+                                                       const char* description,
+                                                       void* reserved) = 0;
   virtual void grpc_call_ref(grpc_call* call) = 0;
   virtual void grpc_call_unref(grpc_call* call) = 0;
   virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0;
diff --git a/include/grpc++/impl/codegen/metadata_map.h b/include/grpc++/impl/codegen/metadata_map.h
index fd4750e..b739859 100644
--- a/include/grpc++/impl/codegen/metadata_map.h
+++ b/include/grpc++/impl/codegen/metadata_map.h
@@ -23,7 +23,6 @@
 
 namespace grpc {
 
-namespace internal {
 class MetadataMap {
  public:
   MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
@@ -51,7 +50,6 @@
   grpc_metadata_array arr_;
   std::multimap<grpc::string_ref, grpc::string_ref> map_;
 };
-}  // namespace internal
 
 }  // namespace grpc
 
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index 87e9e5e..15e24bd 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -25,7 +25,6 @@
 
 namespace grpc {
 
-namespace internal {
 /// A wrapper class of an application provided rpc method handler.
 template <class ServiceType, class RequestType, class ResponseType>
 class RpcMethodHandler : public MethodHandler {
@@ -266,7 +265,6 @@
   }
 };
 
-}  // namespace internal
 }  // namespace grpc
 
 #endif  // GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index fcb4453..67e8f71 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -39,7 +39,8 @@
 
 const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024;
 
-class GrpcBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
+class GrpcBufferWriter final
+    : public ::grpc::protobuf::io::ZeroCopyOutputStream {
  public:
   explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size)
       : block_size_(block_size), byte_count_(0), have_backup_(false) {
@@ -87,8 +88,6 @@
 
   grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
 
-  grpc_slice_buffer* SliceBuffer() { return slice_buffer_; }
-
  private:
   friend class GrpcBufferWriterPeer;
   const int block_size_;
@@ -99,7 +98,8 @@
   grpc_slice slice_;
 };
 
-class GrpcBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
+class GrpcBufferReader final
+    : public ::grpc::protobuf::io::ZeroCopyInputStream {
  public:
   explicit GrpcBufferReader(grpc_byte_buffer* buffer)
       : byte_count_(0), backup_count_(0), status_() {
@@ -160,7 +160,7 @@
     return byte_count_ - backup_count_;
   }
 
- protected:
+ private:
   int64_t byte_count_;
   int64_t backup_count_;
   grpc_byte_buffer_reader reader_;
@@ -168,83 +168,57 @@
   Status status_;
 };
 
-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");
-  *own_buffer = true;
-  int byte_size = msg.ByteSize();
-  if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) {
-    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);
-    return g_core_codegen_interface->ok();
-  } else {
-    BufferWriter writer(bp, internal::kGrpcBufferWriterMaxBufferLength);
-    return msg.SerializeToZeroCopyStream(&writer)
-               ? g_core_codegen_interface->ok()
-               : Status(StatusCode::INTERNAL, "Failed to serialize message");
-  }
-}
-
-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");
-  if (buffer == nullptr) {
-    return Status(StatusCode::INTERNAL, "No payload");
-  }
-  Status result = g_core_codegen_interface->ok();
-  {
-    BufferReader reader(buffer);
-    if (!reader.status().ok()) {
-      return reader.status();
-    }
-    ::grpc::protobuf::io::CodedInputStream decoder(&reader);
-    decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
-    if (!msg->ParseFromCodedStream(&decoder)) {
-      result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
-    }
-    if (!decoder.ConsumedEntireMessage()) {
-      result = Status(StatusCode::INTERNAL, "Did not read entire message");
-    }
-  }
-  g_core_codegen_interface->grpc_byte_buffer_destroy(buffer);
-  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
-// This class provides a protobuf serializer. It translates between protobuf
-// objects and grpc_byte_buffers. More information about SerializationTraits can
-// be found in include/grpc++/impl/codegen/serialization_traits.h.
 template <class T>
 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);
+    *own_buffer = true;
+    int byte_size = msg.ByteSize();
+    if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) {
+      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);
+      return g_core_codegen_interface->ok();
+    } else {
+      internal::GrpcBufferWriter writer(
+          bp, internal::kGrpcBufferWriterMaxBufferLength);
+      return msg.SerializeToZeroCopyStream(&writer)
+                 ? g_core_codegen_interface->ok()
+                 : Status(StatusCode::INTERNAL, "Failed to serialize message");
+    }
   }
 
   static Status Deserialize(grpc_byte_buffer* buffer,
                             grpc::protobuf::Message* msg) {
-    return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer,
-                                                                       msg);
+    if (buffer == nullptr) {
+      return Status(StatusCode::INTERNAL, "No payload");
+    }
+    Status result = g_core_codegen_interface->ok();
+    {
+      internal::GrpcBufferReader reader(buffer);
+      if (!reader.status().ok()) {
+        return reader.status();
+      }
+      ::grpc::protobuf::io::CodedInputStream decoder(&reader);
+      decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
+      if (!msg->ParseFromCodedStream(&decoder)) {
+        result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
+      }
+      if (!decoder.ConsumedEntireMessage()) {
+        result = Status(StatusCode::INTERNAL, "Did not read entire message");
+      }
+    }
+    g_core_codegen_interface->grpc_byte_buffer_destroy(buffer);
+    return result;
   }
 };
-#endif
 
 }  // namespace grpc
 
diff --git a/include/grpc++/impl/codegen/rpc_method.h b/include/grpc++/impl/codegen/rpc_method.h
index 54e5236..ac13ac5 100644
--- a/include/grpc++/impl/codegen/rpc_method.h
+++ b/include/grpc++/impl/codegen/rpc_method.h
@@ -24,7 +24,7 @@
 #include <grpc++/impl/codegen/channel_interface.h>
 
 namespace grpc {
-namespace internal {
+
 /// Descriptor of an RPC method
 class RpcMethod {
  public:
@@ -55,7 +55,6 @@
   void* const channel_tag_;
 };
 
-}  // namespace internal
 }  // namespace grpc
 
 #endif  // GRPCXX_IMPL_CODEGEN_RPC_METHOD_H
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 635e404..7165774 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -35,8 +35,8 @@
 
 namespace grpc {
 class ServerContext;
+class StreamContextInterface;
 
-namespace internal {
 /// Base class for running an RPC handler.
 class MethodHandler {
  public:
@@ -71,7 +71,6 @@
   void* server_tag_;
   std::unique_ptr<MethodHandler> handler_;
 };
-}  // namespace internal
 
 }  // namespace grpc
 
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index a2d6967..b5e37fd 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -55,6 +55,7 @@
 namespace internal {
 template <class W, class R>
 class ServerReaderWriterBody;
+}
 template <class ServiceType, class RequestType, class ResponseType>
 class RpcMethodHandler;
 template <class ServiceType, class RequestType, class ResponseType>
@@ -64,11 +65,9 @@
 template <class ServiceType, class RequestType, class ResponseType>
 class BidiStreamingHandler;
 class UnknownMethodHandler;
-template <class Streamer, bool WriteNeeded>
-class TemplatedBidiStreamingHandler;
-class Call;
-}  // namespace internal
 
+class Call;
+class CallOpBuffer;
 class CompletionQueue;
 class Server;
 class ServerInterface;
@@ -248,14 +247,14 @@
   template <class W, class R>
   friend class ::grpc::internal::ServerReaderWriterBody;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::RpcMethodHandler;
+  friend class RpcMethodHandler;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::ClientStreamingHandler;
+  friend class ClientStreamingHandler;
   template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc::internal::ServerStreamingHandler;
+  friend class ServerStreamingHandler;
   template <class Streamer, bool WriteNeeded>
-  friend class ::grpc::internal::TemplatedBidiStreamingHandler;
-  friend class ::grpc::internal::UnknownMethodHandler;
+  friend class TemplatedBidiStreamingHandler;
+  friend class UnknownMethodHandler;
   friend class ::grpc::ClientContext;
 
   /// Prevent copying.
@@ -264,9 +263,9 @@
 
   class CompletionOp;
 
-  void BeginCompletionOp(internal::Call* call);
+  void BeginCompletionOp(Call* call);
   /// Return the tag queued by BeginCompletionOp()
-  internal::CompletionQueueTag* GetCompletionOpTag();
+  CompletionQueueTag* GetCompletionOpTag();
 
   ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
 
@@ -283,7 +282,7 @@
   CompletionQueue* cq_;
   bool sent_initial_metadata_;
   mutable std::shared_ptr<const AuthContext> auth_context_;
-  internal::MetadataMap client_metadata_;
+  MetadataMap client_metadata_;
   std::multimap<grpc::string, grpc::string> initial_metadata_;
   std::multimap<grpc::string, grpc::string> trailing_metadata_;
 
@@ -291,9 +290,7 @@
   grpc_compression_level compression_level_;
   grpc_compression_algorithm compression_algorithm_;
 
-  internal::CallOpSet<internal::CallOpSendInitialMetadata,
-                      internal::CallOpSendMessage>
-      pending_ops_;
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> pending_ops_;
   bool has_pending_ops_;
 };
 
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 9d12003..55937f1 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -28,22 +28,22 @@
 namespace grpc {
 
 class AsyncGenericService;
+class Channel;
 class GenericServerContext;
+class RpcService;
+class ServerAsyncStreamingInterface;
 class ServerCompletionQueue;
 class ServerContext;
 class ServerCredentials;
 class Service;
+class ThreadPoolInterface;
 
 extern CoreCodegenInterface* g_core_codegen_interface;
 
 /// Models a gRPC server.
 ///
 /// Servers are configured and started via \a grpc::ServerBuilder.
-namespace internal {
-class ServerAsyncStreamingInterface;
-}  // namespace internal
-
-class ServerInterface : public internal::CallHook {
+class ServerInterface : public CallHook {
  public:
   virtual ~ServerInterface() {}
 
@@ -78,7 +78,7 @@
   virtual void Wait() = 0;
 
  protected:
-  friend class ::grpc::Service;
+  friend class Service;
 
   /// Register a service. This call does not take ownership of the service.
   /// The service must exist for the lifetime of the Server instance.
@@ -116,13 +116,12 @@
 
   virtual grpc_server* server() = 0;
 
-  virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                                internal::Call* call) = 0;
+  virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
 
-  class BaseAsyncRequest : public internal::CompletionQueueTag {
+  class BaseAsyncRequest : public CompletionQueueTag {
    public:
     BaseAsyncRequest(ServerInterface* server, ServerContext* context,
-                     internal::ServerAsyncStreamingInterface* stream,
+                     ServerAsyncStreamingInterface* stream,
                      CompletionQueue* call_cq, void* tag,
                      bool delete_on_finalize);
     virtual ~BaseAsyncRequest();
@@ -132,7 +131,7 @@
    protected:
     ServerInterface* const server_;
     ServerContext* const context_;
-    internal::ServerAsyncStreamingInterface* const stream_;
+    ServerAsyncStreamingInterface* const stream_;
     CompletionQueue* const call_cq_;
     void* const tag_;
     const bool delete_on_finalize_;
@@ -142,7 +141,7 @@
   class RegisteredAsyncRequest : public BaseAsyncRequest {
    public:
     RegisteredAsyncRequest(ServerInterface* server, ServerContext* context,
-                           internal::ServerAsyncStreamingInterface* stream,
+                           ServerAsyncStreamingInterface* stream,
                            CompletionQueue* call_cq, void* tag);
 
     // uses BaseAsyncRequest::FinalizeResult
@@ -156,7 +155,7 @@
    public:
     NoPayloadAsyncRequest(void* registered_method, ServerInterface* server,
                           ServerContext* context,
-                          internal::ServerAsyncStreamingInterface* stream,
+                          ServerAsyncStreamingInterface* stream,
                           CompletionQueue* call_cq,
                           ServerCompletionQueue* notification_cq, void* tag)
         : RegisteredAsyncRequest(server, context, stream, call_cq, tag) {
@@ -171,33 +170,60 @@
    public:
     PayloadAsyncRequest(void* registered_method, ServerInterface* server,
                         ServerContext* context,
-                        internal::ServerAsyncStreamingInterface* stream,
+                        ServerAsyncStreamingInterface* stream,
                         CompletionQueue* call_cq,
                         ServerCompletionQueue* notification_cq, void* tag,
                         Message* request)
         : RegisteredAsyncRequest(server, context, stream, call_cq, tag),
+          registered_method_(registered_method),
+          server_(server),
+          context_(context),
+          stream_(stream),
+          call_cq_(call_cq),
+          notification_cq_(notification_cq),
+          tag_(tag),
           request_(request) {
       IssueRequest(registered_method, &payload_, notification_cq);
     }
 
     bool FinalizeResult(void** tag, bool* status) override {
-      bool serialization_status =
-          *status && payload_ &&
-          SerializationTraits<Message>::Deserialize(payload_, request_).ok();
-      bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
-      *status = serialization_status && *status;
-      return ret;
+      if (*status) {
+        if (payload_ == nullptr ||
+            !SerializationTraits<Message>::Deserialize(payload_, 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
+          // the application.
+          g_core_codegen_interface->grpc_call_cancel_with_status(
+              call_, GRPC_STATUS_INTERNAL, "Unable to parse request", nullptr);
+          g_core_codegen_interface->grpc_call_unref(call_);
+          new PayloadAsyncRequest(registered_method_, server_, context_,
+                                  stream_, call_cq_, notification_cq_, tag_,
+                                  request_);
+          delete this;
+          return false;
+        }
+      }
+      return RegisteredAsyncRequest::FinalizeResult(tag, status);
     }
 
    private:
-    grpc_byte_buffer* payload_;
+    void* const registered_method_;
+    ServerInterface* const server_;
+    ServerContext* const context_;
+    ServerAsyncStreamingInterface* const stream_;
+    CompletionQueue* const call_cq_;
+    ServerCompletionQueue* const notification_cq_;
+    void* const tag_;
     Message* const request_;
+    grpc_byte_buffer* payload_;
   };
 
   class GenericAsyncRequest : public BaseAsyncRequest {
    public:
     GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
-                        internal::ServerAsyncStreamingInterface* stream,
+                        ServerAsyncStreamingInterface* stream,
                         CompletionQueue* call_cq,
                         ServerCompletionQueue* notification_cq, void* tag,
                         bool delete_on_finalize);
@@ -209,9 +235,8 @@
   };
 
   template <class Message>
-  void RequestAsyncCall(internal::RpcServiceMethod* method,
-                        ServerContext* context,
-                        internal::ServerAsyncStreamingInterface* stream,
+  void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context,
+                        ServerAsyncStreamingInterface* stream,
                         CompletionQueue* call_cq,
                         ServerCompletionQueue* notification_cq, void* tag,
                         Message* message) {
@@ -221,9 +246,8 @@
                                      message);
   }
 
-  void RequestAsyncCall(internal::RpcServiceMethod* method,
-                        ServerContext* context,
-                        internal::ServerAsyncStreamingInterface* stream,
+  void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context,
+                        ServerAsyncStreamingInterface* stream,
                         CompletionQueue* call_cq,
                         ServerCompletionQueue* notification_cq, void* tag) {
     GPR_CODEGEN_ASSERT(method);
@@ -232,7 +256,7 @@
   }
 
   void RequestAsyncGenericCall(GenericServerContext* context,
-                               internal::ServerAsyncStreamingInterface* stream,
+                               ServerAsyncStreamingInterface* stream,
                                CompletionQueue* call_cq,
                                ServerCompletionQueue* notification_cq,
                                void* tag) {
diff --git a/include/grpc++/impl/codegen/service_type.h b/include/grpc++/impl/codegen/service_type.h
index 71c3d99..2dc4ea0 100644
--- a/include/grpc++/impl/codegen/service_type.h
+++ b/include/grpc++/impl/codegen/service_type.h
@@ -28,14 +28,13 @@
 
 namespace grpc {
 
+class Call;
 class CompletionQueue;
 class Server;
 class ServerInterface;
 class ServerCompletionQueue;
 class ServerContext;
 
-namespace internal {
-class Call;
 class ServerAsyncStreamingInterface {
  public:
   virtual ~ServerAsyncStreamingInterface() {}
@@ -49,10 +48,9 @@
   virtual void SendInitialMetadata(void* tag) = 0;
 
  private:
-  friend class ::grpc::ServerInterface;
+  friend class ServerInterface;
   virtual void BindCall(Call* call) = 0;
 };
-}  // namespace internal
 
 /// Desriptor of an RPC service and its various RPC methods
 class Service {
@@ -90,38 +88,40 @@
  protected:
   template <class Message>
   void RequestAsyncUnary(int index, ServerContext* context, Message* request,
-                         internal::ServerAsyncStreamingInterface* stream,
+                         ServerAsyncStreamingInterface* stream,
                          CompletionQueue* call_cq,
                          ServerCompletionQueue* notification_cq, void* tag) {
     server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
                               notification_cq, tag, request);
   }
-  void RequestAsyncClientStreaming(
-      int index, ServerContext* context,
-      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-      ServerCompletionQueue* notification_cq, void* tag) {
+  void RequestAsyncClientStreaming(int index, ServerContext* context,
+                                   ServerAsyncStreamingInterface* stream,
+                                   CompletionQueue* call_cq,
+                                   ServerCompletionQueue* notification_cq,
+                                   void* tag) {
     server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
                               notification_cq, tag);
   }
   template <class Message>
-  void RequestAsyncServerStreaming(
-      int index, ServerContext* context, Message* request,
-      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-      ServerCompletionQueue* notification_cq, void* tag) {
+  void RequestAsyncServerStreaming(int index, ServerContext* context,
+                                   Message* request,
+                                   ServerAsyncStreamingInterface* stream,
+                                   CompletionQueue* call_cq,
+                                   ServerCompletionQueue* notification_cq,
+                                   void* tag) {
     server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
                               notification_cq, tag, request);
   }
-  void RequestAsyncBidiStreaming(
-      int index, ServerContext* context,
-      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-      ServerCompletionQueue* notification_cq, void* tag) {
+  void RequestAsyncBidiStreaming(int index, ServerContext* context,
+                                 ServerAsyncStreamingInterface* stream,
+                                 CompletionQueue* call_cq,
+                                 ServerCompletionQueue* notification_cq,
+                                 void* tag) {
     server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
                               notification_cq, tag);
   }
 
-  void AddMethod(internal::RpcServiceMethod* method) {
-    methods_.emplace_back(method);
-  }
+  void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
 
   void MarkMethodAsync(int index) {
     GPR_CODEGEN_ASSERT(
@@ -139,7 +139,7 @@
     methods_[index].reset();
   }
 
-  void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
+  void MarkMethodStreamed(int index, MethodHandler* streamed_method) {
     GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() &&
                        "Cannot mark an async or generic method Streamed");
     methods_[index]->SetHandler(streamed_method);
@@ -148,14 +148,14 @@
     // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
     // and split server-side streaming is BIDI_STREAMING with 1 read and
     // any number of writes, in that order.
-    methods_[index]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
+    methods_[index]->SetMethodType(::grpc::RpcMethod::BIDI_STREAMING);
   }
 
  private:
   friend class Server;
   friend class ServerInterface;
   ServerInterface* server_;
-  std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
+  std::vector<std::unique_ptr<RpcServiceMethod>> methods_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/status.h b/include/grpc++/impl/codegen/status.h
index 51fca9f..6f013cf 100644
--- a/include/grpc++/impl/codegen/status.h
+++ b/include/grpc++/impl/codegen/status.h
@@ -63,6 +63,11 @@
   /// Is the status OK?
   bool ok() const { return code_ == StatusCode::OK; }
 
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const {}
+
  private:
   StatusCode code_;
   grpc::string error_message_;
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index f9c8303..3fa2089 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -30,7 +30,6 @@
 
 namespace grpc {
 
-namespace internal {
 /// Common interface for all synchronous client side streaming.
 class ClientStreamingInterface {
  public:
@@ -63,6 +62,20 @@
   virtual Status Finish() = 0;
 };
 
+/// Common interface for all synchronous server side streaming.
+class ServerStreamingInterface {
+ public:
+  virtual ~ServerStreamingInterface() {}
+
+  /// Block to send initial metadata to client.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// The initial metadata that will be sent to the client will be
+  /// taken from the \a ServerContext associated with the call.
+  virtual void SendInitialMetadata() = 0;
+};
+
 /// An interface that yields a sequence of messages of type \a R.
 template <class R>
 class ReaderInterface {
@@ -128,12 +141,10 @@
   }
 };
 
-}  // namespace internal
-
 /// Client-side interface for streaming reads of message of type \a R.
 template <class R>
-class ClientReaderInterface : public internal::ClientStreamingInterface,
-                              public internal::ReaderInterface<R> {
+class ClientReaderInterface : public ClientStreamingInterface,
+                              public ReaderInterface<R> {
  public:
   /// Block to wait for initial metadata from server. The received metadata
   /// can only be accessed after this call returns. Should only be called before
@@ -142,57 +153,34 @@
   virtual void WaitForInitialMetadata() = 0;
 };
 
-/// Client-side interface for streaming writes of message type \a W.
-template <class W>
-class ClientWriterInterface : public internal::ClientStreamingInterface,
-                              public internal::WriterInterface<W> {
- public:
-  /// Half close writing from the client. (signal that the stream of messages
-  /// coming from the clinet is complete).
-  /// Blocks until currently-pending writes are completed.
-  /// Thread safe with respect to \a ReaderInterface::Read operations only
-  ///
-  /// \return Whether the writes were successful.
-  virtual bool WritesDone() = 0;
-};
-
-/// Client-side interface for bi-directional streaming with
-/// client-to-server stream messages of type \a W and
-/// server-to-client stream messages of type \a R.
-template <class W, class R>
-class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
-                                    public internal::WriterInterface<W>,
-                                    public internal::ReaderInterface<R> {
- public:
-  /// Block to wait for initial metadata from server. The received metadata
-  /// can only be accessed after this call returns. Should only be called before
-  /// the first read. Calling this method is optional, and if it is not called
-  /// the metadata will be available in ClientContext after the first read.
-  virtual void WaitForInitialMetadata() = 0;
-
-  /// Half close writing from the client. (signal that the stream of messages
-  /// coming from the clinet is complete).
-  /// Blocks until currently-pending writes are completed.
-  /// Thread-safe with respect to \a ReaderInterface::Read
-  ///
-  /// \return Whether the writes were successful.
-  virtual bool WritesDone() = 0;
-};
-
 /// Synchronous (blocking) client-side API for doing server-streaming RPCs,
 /// where the stream of messages coming from the server has messages
 /// of type \a R.
 template <class R>
 class ClientReader final : public ClientReaderInterface<R> {
  public:
-  struct internal {
-    template <class W>
-    static ClientReader* Create(::grpc::ChannelInterface* channel,
-                                const ::grpc::internal::RpcMethod& method,
-                                ClientContext* context, const W& request) {
-      return new ClientReader(channel, method, context, request);
-    }
-  };
+  /// Block to create a stream and write the initial metadata and \a request
+  /// out. Note that \a context will be used to fill in custom initial
+  /// metadata used to send to the server when starting the call.
+  template <class W>
+  ClientReader(ChannelInterface* channel, const RpcMethod& method,
+               ClientContext* context, const W& request)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpClientSendClose>
+        ops;
+    ops.SendInitialMetadata(context->send_initial_metadata_,
+                            context->initial_metadata_flags());
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
+    ops.ClientSendClose();
+    call_.PerformOps(&ops);
+    cq_.Pluck(&ops);
+  }
 
   /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
   /// semantics.
@@ -204,8 +192,7 @@
   void WaitForInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata> ops;
     ops.RecvInitialMetadata(context_);
     call_.PerformOps(&ops);
     cq_.Pluck(&ops);  /// status ignored
@@ -222,9 +209,7 @@
   ///   already received (if initial metadata is received, it can be then
   ///   accessed through the \a ClientContext associated with this call).
   bool Read(R* msg) override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                                ::grpc::internal::CallOpRecvMessage<R>>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
     if (!context_->initial_metadata_received_) {
       ops.RecvInitialMetadata(context_);
     }
@@ -239,7 +224,7 @@
   ///   The \a ClientContext associated with this call is updated with
   ///   possible metadata received from the server.
   Status Finish() override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientRecvStatus> ops;
+    CallOpSet<CallOpClientRecvStatus> ops;
     Status status;
     ops.ClientRecvStatus(context_, &status);
     call_.PerformOps(&ops);
@@ -250,48 +235,53 @@
  private:
   ClientContext* context_;
   CompletionQueue cq_;
-  ::grpc::internal::Call call_;
+  Call call_;
+};
 
-  /// Block to create a stream and write the initial metadata and \a request
-  /// out. Note that \a context will be used to fill in custom initial
-  /// metadata used to send to the server when starting the call.
-  template <class W>
-  ClientReader(::grpc::ChannelInterface* channel,
-               const ::grpc::internal::RpcMethod& method,
-               ClientContext* context, const W& request)
-      : context_(context),
-        cq_(grpc_completion_queue_attributes{
-            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
-            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
-        call_(channel->CreateCall(method, context, &cq_)) {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                                ::grpc::internal::CallOpSendMessage,
-                                ::grpc::internal::CallOpClientSendClose>
-        ops;
-    ops.SendInitialMetadata(context->send_initial_metadata_,
-                            context->initial_metadata_flags());
-    // TODO(ctiller): don't assert
-    GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
-    ops.ClientSendClose();
-    call_.PerformOps(&ops);
-    cq_.Pluck(&ops);
-  }
+/// Client-side interface for streaming writes of message type \a W.
+template <class W>
+class ClientWriterInterface : public ClientStreamingInterface,
+                              public WriterInterface<W> {
+ public:
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the clinet is complete).
+  /// Blocks until currently-pending writes are completed.
+  /// Thread safe with respect to \a ReaderInterface::Read operations only
+  ///
+  /// \return Whether the writes were successful.
+  virtual bool WritesDone() = 0;
 };
 
 /// Synchronous (blocking) client-side API for doing client-streaming RPCs,
 /// where the outgoing message stream coming from the client has messages of
 /// type \a W.
 template <class W>
-class ClientWriter final : public ClientWriterInterface<W> {
+class ClientWriter : public ClientWriterInterface<W> {
  public:
-  struct internal {
-    template <class R>
-    static ClientWriter* Create(::grpc::ChannelInterface* channel,
-                                const ::grpc::internal::RpcMethod& method,
-                                ClientContext* context, R* response) {
-      return new ClientWriter(channel, method, context, response);
+  /// Block to create a stream (i.e. send request headers and other initial
+  /// metadata to the server). Note that \a context will be used to fill
+  /// in custom initial metadata. \a response will be filled in with the
+  /// single expected response message from the server upon a successful
+  /// call to the \a Finish method of this instance.
+  template <class R>
+  ClientWriter(ChannelInterface* channel, const RpcMethod& method,
+               ClientContext* context, R* response)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    finish_ops_.RecvMessage(response);
+    finish_ops_.AllowNoMessage();
+
+    if (!context_->initial_metadata_corked_) {
+      CallOpSet<CallOpSendInitialMetadata> ops;
+      ops.SendInitialMetadata(context->send_initial_metadata_,
+                              context->initial_metadata_flags());
+      call_.PerformOps(&ops);
+      cq_.Pluck(&ops);
     }
-  };
+  }
 
   /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
   /// semantics.
@@ -302,8 +292,7 @@
   void WaitForInitialMetadata() {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata> ops;
     ops.RecvInitialMetadata(context_);
     call_.PerformOps(&ops);
     cq_.Pluck(&ops);  // status ignored
@@ -315,11 +304,10 @@
   /// Side effect:
   ///   Also sends initial metadata if not already sent (using the
   ///   \a ClientContext associated with this call).
-  using ::grpc::internal::WriterInterface<W>::Write;
+  using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                                ::grpc::internal::CallOpSendMessage,
-                                ::grpc::internal::CallOpClientSendClose>
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpClientSendClose>
         ops;
 
     if (options.is_last_message()) {
@@ -340,7 +328,7 @@
   }
 
   bool WritesDone() override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+    CallOpSet<CallOpClientSendClose> ops;
     ops.ClientSendClose();
     call_.PerformOps(&ops);
     return cq_.Pluck(&ops);
@@ -365,39 +353,34 @@
 
  private:
   ClientContext* context_;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                              ::grpc::internal::CallOpGenericRecvMessage,
-                              ::grpc::internal::CallOpClientRecvStatus>
+  CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
+            CallOpClientRecvStatus>
       finish_ops_;
   CompletionQueue cq_;
-  ::grpc::internal::Call call_;
+  Call call_;
+};
 
-  /// Block to create a stream (i.e. send request headers and other initial
-  /// metadata to the server). Note that \a context will be used to fill
-  /// in custom initial metadata. \a response will be filled in with the
-  /// single expected response message from the server upon a successful
-  /// call to the \a Finish method of this instance.
-  template <class R>
-  ClientWriter(::grpc::ChannelInterface* channel,
-               const ::grpc::internal::RpcMethod& method,
-               ClientContext* context, R* response)
-      : context_(context),
-        cq_(grpc_completion_queue_attributes{
-            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
-            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
-        call_(channel->CreateCall(method, context, &cq_)) {
-    finish_ops_.RecvMessage(response);
-    finish_ops_.AllowNoMessage();
+/// Client-side interface for bi-directional streaming with
+/// client-to-server stream messages of type \a W and
+/// server-to-client stream messages of type \a R.
+template <class W, class R>
+class ClientReaderWriterInterface : public ClientStreamingInterface,
+                                    public WriterInterface<W>,
+                                    public ReaderInterface<R> {
+ public:
+  /// Block to wait for initial metadata from server. The received metadata
+  /// can only be accessed after this call returns. Should only be called before
+  /// the first read. Calling this method is optional, and if it is not called
+  /// the metadata will be available in ClientContext after the first read.
+  virtual void WaitForInitialMetadata() = 0;
 
-    if (!context_->initial_metadata_corked_) {
-      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-          ops;
-      ops.SendInitialMetadata(context->send_initial_metadata_,
-                              context->initial_metadata_flags());
-      call_.PerformOps(&ops);
-      cq_.Pluck(&ops);
-    }
-  }
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the clinet is complete).
+  /// Blocks until currently-pending writes are completed.
+  /// Thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \return Whether the writes were successful.
+  virtual bool WritesDone() = 0;
 };
 
 /// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
@@ -407,13 +390,24 @@
 template <class W, class R>
 class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
  public:
-  struct internal {
-    static ClientReaderWriter* Create(::grpc::ChannelInterface* channel,
-                                      const ::grpc::internal::RpcMethod& method,
-                                      ClientContext* context) {
-      return new ClientReaderWriter(channel, method, context);
+  /// Block to create a stream and write the initial metadata and \a request
+  /// out. Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
+                     ClientContext* context)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    if (!context_->initial_metadata_corked_) {
+      CallOpSet<CallOpSendInitialMetadata> ops;
+      ops.SendInitialMetadata(context->send_initial_metadata_,
+                              context->initial_metadata_flags());
+      call_.PerformOps(&ops);
+      cq_.Pluck(&ops);
     }
-  };
+  }
 
   /// Block waiting to read initial metadata from the server.
   /// This call is optional, but if it is used, it cannot be used concurrently
@@ -424,8 +418,7 @@
   void WaitForInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata> ops;
     ops.RecvInitialMetadata(context_);
     call_.PerformOps(&ops);
     cq_.Pluck(&ops);  // status ignored
@@ -441,9 +434,7 @@
   ///   Also receives initial metadata if not already received (updates the \a
   ///   ClientContext associated with this call in that case).
   bool Read(R* msg) override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                                ::grpc::internal::CallOpRecvMessage<R>>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
     if (!context_->initial_metadata_received_) {
       ops.RecvInitialMetadata(context_);
     }
@@ -457,11 +448,10 @@
   /// Side effect:
   ///   Also sends initial metadata if not already sent (using the
   ///   \a ClientContext associated with this call to fill in values).
-  using ::grpc::internal::WriterInterface<W>::Write;
+  using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                                ::grpc::internal::CallOpSendMessage,
-                                ::grpc::internal::CallOpClientSendClose>
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpClientSendClose>
         ops;
 
     if (options.is_last_message()) {
@@ -482,7 +472,7 @@
   }
 
   bool WritesDone() override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+    CallOpSet<CallOpClientSendClose> ops;
     ops.ClientSendClose();
     call_.PerformOps(&ops);
     return cq_.Pluck(&ops);
@@ -494,9 +484,7 @@
   ///   - the \a ClientContext associated with this call is updated with
   ///     possible trailing metadata sent from the server.
   Status Finish() override {
-    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
-                                ::grpc::internal::CallOpClientRecvStatus>
-        ops;
+    CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> ops;
     if (!context_->initial_metadata_received_) {
       ops.RecvInitialMetadata(context_);
     }
@@ -510,61 +498,13 @@
  private:
   ClientContext* context_;
   CompletionQueue cq_;
-  ::grpc::internal::Call call_;
-
-  /// Block to create a stream and write the initial metadata and \a request
-  /// out. Note that \a context will be used to fill in custom initial metadata
-  /// used to send to the server when starting the call.
-  ClientReaderWriter(::grpc::ChannelInterface* channel,
-                     const ::grpc::internal::RpcMethod& method,
-                     ClientContext* context)
-      : context_(context),
-        cq_(grpc_completion_queue_attributes{
-            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
-            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
-        call_(channel->CreateCall(method, context, &cq_)) {
-    if (!context_->initial_metadata_corked_) {
-      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
-          ops;
-      ops.SendInitialMetadata(context->send_initial_metadata_,
-                              context->initial_metadata_flags());
-      call_.PerformOps(&ops);
-      cq_.Pluck(&ops);
-    }
-  }
+  Call call_;
 };
 
-namespace internal {
-/// Common interface for all synchronous server side streaming.
-class ServerStreamingInterface {
- public:
-  virtual ~ServerStreamingInterface() {}
-
-  /// Block to send initial metadata to client.
-  /// This call is optional, but if it is used, it cannot be used concurrently
-  /// with or after the \a Finish method.
-  ///
-  /// The initial metadata that will be sent to the client will be
-  /// taken from the \a ServerContext associated with the call.
-  virtual void SendInitialMetadata() = 0;
-};
-}  // namespace internal
-
 /// Server-side interface for streaming reads of message of type \a R.
 template <class R>
-class ServerReaderInterface : public internal::ServerStreamingInterface,
-                              public internal::ReaderInterface<R> {};
-
-/// Server-side interface for streaming writes of message of type \a W.
-template <class W>
-class ServerWriterInterface : public internal::ServerStreamingInterface,
-                              public internal::WriterInterface<W> {};
-
-/// Server-side interface for bi-directional streaming.
-template <class W, class R>
-class ServerReaderWriterInterface : public internal::ServerStreamingInterface,
-                                    public internal::WriterInterface<W>,
-                                    public internal::ReaderInterface<R> {};
+class ServerReaderInterface : public ServerStreamingInterface,
+                              public ReaderInterface<R> {};
 
 /// Synchronous (blocking) server-side API for doing client-streaming RPCs,
 /// where the incoming message stream coming from the client has messages of
@@ -572,13 +512,15 @@
 template <class R>
 class ServerReader final : public ServerReaderInterface<R> {
  public:
+  ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
+
   /// See the \a ServerStreamingInterface.SendInitialMetadata method
   /// for semantics. Note that initial metadata will be affected by the
   /// \a ServerContext associated with this call.
   void SendInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
-    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+    CallOpSet<CallOpSendInitialMetadata> ops;
     ops.SendInitialMetadata(ctx_->initial_metadata_,
                             ctx_->initial_metadata_flags());
     if (ctx_->compression_level_set()) {
@@ -595,29 +537,30 @@
   }
 
   bool Read(R* msg) override {
-    internal::CallOpSet<internal::CallOpRecvMessage<R>> ops;
+    CallOpSet<CallOpRecvMessage<R>> ops;
     ops.RecvMessage(msg);
     call_->PerformOps(&ops);
     return call_->cq()->Pluck(&ops) && ops.got_message;
   }
 
  private:
-  internal::Call* const call_;
+  Call* const call_;
   ServerContext* const ctx_;
-
-  template <class ServiceType, class RequestType, class ResponseType>
-  friend class internal::ClientStreamingHandler;
-
-  ServerReader(internal::Call* call, ServerContext* ctx)
-      : call_(call), ctx_(ctx) {}
 };
 
+/// Server-side interface for streaming writes of message of type \a W.
+template <class W>
+class ServerWriterInterface : public ServerStreamingInterface,
+                              public WriterInterface<W> {};
+
 /// Synchronous (blocking) server-side API for doing for doing a
 /// server-streaming RPCs, where the outgoing message stream coming from the
 /// server has messages of type \a W.
 template <class W>
 class ServerWriter final : public ServerWriterInterface<W> {
  public:
+  ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
+
   /// See the \a ServerStreamingInterface.SendInitialMetadata method
   /// for semantics.
   /// Note that initial metadata will be affected by the
@@ -625,7 +568,7 @@
   void SendInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
-    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+    CallOpSet<CallOpSendInitialMetadata> ops;
     ops.SendInitialMetadata(ctx_->initial_metadata_,
                             ctx_->initial_metadata_flags());
     if (ctx_->compression_level_set()) {
@@ -641,12 +584,11 @@
   /// Side effect:
   ///   Also sends initial metadata if not already sent (using the
   ///   \a ClientContext associated with this call to fill in values).
-  using internal::WriterInterface<W>::Write;
+  using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     if (options.is_last_message()) {
       options.set_buffer_hint();
     }
-
     if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
       return false;
     }
@@ -671,16 +613,16 @@
   }
 
  private:
-  internal::Call* const call_;
+  Call* const call_;
   ServerContext* const ctx_;
-
-  template <class ServiceType, class RequestType, class ResponseType>
-  friend class internal::ServerStreamingHandler;
-
-  ServerWriter(internal::Call* call, ServerContext* ctx)
-      : call_(call), ctx_(ctx) {}
 };
 
+/// Server-side interface for bi-directional streaming.
+template <class W, class R>
+class ServerReaderWriterInterface : public ServerStreamingInterface,
+                                    public WriterInterface<W>,
+                                    public ReaderInterface<R> {};
+
 /// Actual implementation of bi-directional streaming
 namespace internal {
 template <class W, class R>
@@ -746,7 +688,6 @@
   Call* const call_;
   ServerContext* const ctx_;
 };
-
 }  // namespace internal
 
 /// Synchronous (blocking) server-side API for a bidirectional
@@ -756,6 +697,8 @@
 template <class W, class R>
 class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
  public:
+  ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {}
+
   /// See the \a ServerStreamingInterface.SendInitialMetadata method
   /// for semantics. Note that initial metadata will be affected by the
   /// \a ServerContext associated with this call.
@@ -772,18 +715,13 @@
   /// Side effect:
   ///   Also sends initial metadata if not already sent (using the \a
   ///   ServerContext associated with this call).
-  using internal::WriterInterface<W>::Write;
+  using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     return body_.Write(msg, options);
   }
 
  private:
   internal::ServerReaderWriterBody<W, R> body_;
-
-  friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>,
-                                                       false>;
-  ServerReaderWriter(internal::Call* call, ServerContext* ctx)
-      : body_(call, ctx) {}
 };
 
 /// A class to represent a flow-controlled unary call. This is something
@@ -798,6 +736,9 @@
 class ServerUnaryStreamer final
     : public ServerReaderWriterInterface<ResponseType, RequestType> {
  public:
+  ServerUnaryStreamer(Call* call, ServerContext* ctx)
+      : body_(call, ctx), read_done_(false), write_done_(false) {}
+
   /// Block to send initial metadata to client.
   /// Implicit input parameter:
   ///    - the \a ServerContext associated with this call will be used for
@@ -834,7 +775,7 @@
   /// \param options The WriteOptions affecting the write operation.
   ///
   /// \return \a true on success, \a false when the stream has been closed.
-  using internal::WriterInterface<ResponseType>::Write;
+  using WriterInterface<ResponseType>::Write;
   bool Write(const ResponseType& response, WriteOptions options) override {
     if (write_done_ || !read_done_) {
       return false;
@@ -847,11 +788,6 @@
   internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
   bool read_done_;
   bool write_done_;
-
-  friend class internal::TemplatedBidiStreamingHandler<
-      ServerUnaryStreamer<RequestType, ResponseType>, true>;
-  ServerUnaryStreamer(internal::Call* call, ServerContext* ctx)
-      : body_(call, ctx), read_done_(false), write_done_(false) {}
 };
 
 /// A class to represent a flow-controlled server-side streaming call.
@@ -863,6 +799,9 @@
 class ServerSplitStreamer final
     : public ServerReaderWriterInterface<ResponseType, RequestType> {
  public:
+  ServerSplitStreamer(Call* call, ServerContext* ctx)
+      : body_(call, ctx), read_done_(false) {}
+
   /// Block to send initial metadata to client.
   /// Implicit input parameter:
   ///    - the \a ServerContext associated with this call will be used for
@@ -899,7 +838,7 @@
   /// \param options The WriteOptions affecting the write operation.
   ///
   /// \return \a true on success, \a false when the stream has been closed.
-  using internal::WriterInterface<ResponseType>::Write;
+  using WriterInterface<ResponseType>::Write;
   bool Write(const ResponseType& response, WriteOptions options) override {
     return read_done_ && body_.Write(response, options);
   }
@@ -907,11 +846,6 @@
  private:
   internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
   bool read_done_;
-
-  friend class internal::TemplatedBidiStreamingHandler<
-      ServerSplitStreamer<RequestType, ResponseType>, false>;
-  ServerSplitStreamer(internal::Call* call, ServerContext* ctx)
-      : body_(call, ctx), read_done_(false) {}
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/time.h b/include/grpc++/impl/codegen/time.h
index d464d6e..589deb4 100644
--- a/include/grpc++/impl/codegen/time.h
+++ b/include/grpc++/impl/codegen/time.h
@@ -19,8 +19,6 @@
 #ifndef GRPCXX_IMPL_CODEGEN_TIME_H
 #define GRPCXX_IMPL_CODEGEN_TIME_H
 
-#include <chrono>
-
 #include <grpc++/impl/codegen/config.h>
 #include <grpc/impl/codegen/grpc_types.h>
 
@@ -61,6 +59,10 @@
 
 }  // namespace grpc
 
+#include <chrono>
+
+#include <grpc/impl/codegen/grpc_types.h>
+
 namespace grpc {
 
 // from and to should be absolute time.
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index 1ec9b97..92330d4 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -132,13 +132,17 @@
 /// services.
 std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials();
 
+/// Constant for maximum auth token lifetime.
+constexpr long kMaxAuthTokenLifetimeSecs = 3600;
+
 /// Builds Service Account JWT Access credentials.
 /// json_key is the JSON key string containing the client's private key.
 /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
 /// (JWT) created with this credentials. It should not exceed
-/// \a grpc_max_auth_token_lifetime or will be cropped to this value.
+/// \a kMaxAuthTokenLifetimeSecs or will be cropped to this value.
 std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
-    const grpc::string& json_key, long token_lifetime_seconds);
+    const grpc::string& json_key,
+    long token_lifetime_seconds = kMaxAuthTokenLifetimeSecs);
 
 /// Builds refresh token credentials.
 /// json_refresh_token is the JSON string containing the refresh token along
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index baf0ded..0a3aae8 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -95,6 +95,9 @@
     return health_check_service_.get();
   }
 
+  /// Establish a channel for in-process communication
+  std::shared_ptr<Channel> InProcessChannel(const ChannelArguments& args);
+
  private:
   friend class AsyncGenericService;
   friend class ServerBuilder;
@@ -156,7 +159,7 @@
   ///
   /// \param addr The address to try to bind to the server (eg, localhost:1234,
   /// 192.168.1.1:31416, [::1]:27182, etc.).
-  /// \params creds The credentials associated with the server.
+  /// \param creds The credentials associated with the server.
   ///
   /// \return bound port number on success, 0 on failure.
   ///
@@ -172,8 +175,7 @@
   /// \param num_cqs How many completion queues does \a cqs hold.
   void Start(ServerCompletionQueue** cqs, size_t num_cqs) override;
 
-  void PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                        internal::Call* call) override;
+  void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override;
 
   void ShutdownInternal(gpr_timespec deadline) override;
 
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index 5bd53bd..eafd636 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -40,6 +40,7 @@
 class AsyncGenericService;
 class ResourceQuota;
 class CompletionQueue;
+class RpcService;
 class Server;
 class ServerCompletionQueue;
 class ServerCredentials;
diff --git a/include/grpc++/support/slice.h b/include/grpc++/support/slice.h
index db5cf94..0b4ba7c 100644
--- a/include/grpc++/support/slice.h
+++ b/include/grpc++/support/slice.h
@@ -44,6 +44,20 @@
   /// Construct a slice from \a slice, stealing a reference.
   Slice(grpc_slice slice, StealRef);
 
+  /// Allocate a slice of specified size
+  Slice(size_t len);
+
+  /// Construct a slice from a copied buffer
+  Slice(const void* buf, size_t len);
+
+  /// Construct a slice from a copied string
+  Slice(const grpc::string& str);
+
+  enum StaticSlice { STATIC_SLICE };
+
+  /// Construct a slice from a static buffer
+  Slice(const void* buf, size_t len, StaticSlice);
+
   /// Copy constructor, adds a reference.
   Slice(const Slice& other);
 
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 2cf8de0..943d6e4 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -296,7 +296,11 @@
     If a status has not been received for the call, set it to the status code
     and description passed in.
     Importantly, this function does not send status nor description to the
-    remote endpoint. */
+    remote endpoint.
+    Note that \a description doesn't need be a static string.
+    It doesn't need to be alive after the call to
+    grpc_call_cancel_with_status completes.
+    */
 GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
                                                      grpc_status_code status,
                                                      const char *description,
diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h
index c3b528b..2cfd22a 100644
--- a/include/grpc/impl/codegen/atm.h
+++ b/include/grpc/impl/codegen/atm.h
@@ -60,6 +60,7 @@
    int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n);
    int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n);
    int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n);
+   int gpr_atm_full_cas(gpr_atm *p, gpr_atm o, gpr_atm n);
 
    // Atomically, set *p=n and return the old value of *p
    gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n);
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index f1c457c..bb3c90e 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -333,7 +333,9 @@
   /** this batch of operations leads to more operations than allowed */
   GRPC_CALL_ERROR_BATCH_TOO_BIG,
   /** payload type requested is not the type registered */
-  GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
+  GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH,
+  /** completion queue has been shutdown */
+  GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN
 } grpc_call_error;
 
 /** Default send/receive message size limits in bytes. -1 for unlimited. */
diff --git a/include/grpc/support/avl.h b/include/grpc/support/avl.h
index ed052e8..d53ff5d 100644
--- a/include/grpc/support/avl.h
+++ b/include/grpc/support/avl.h
@@ -31,18 +31,23 @@
   long height;
 } gpr_avl_node;
 
+/** vtable for the AVL tree
+ * The optional user_data is propagated from the top level gpr_avl_XXX API.
+ * From the same API call, multiple vtable functions may be called multiple
+ * times.
+ */
 typedef struct gpr_avl_vtable {
   /** destroy a key */
-  void (*destroy_key)(void *key);
+  void (*destroy_key)(void *key, void *user_data);
   /** copy a key, returning new value */
-  void *(*copy_key)(void *key);
+  void *(*copy_key)(void *key, void *user_data);
   /** compare key1, key2; return <0 if key1 < key2,
       >0 if key1 > key2, 0 if key1 == key2 */
-  long (*compare_keys)(void *key1, void *key2);
+  long (*compare_keys)(void *key1, void *key2, void *user_data);
   /** destroy a value */
-  void (*destroy_value)(void *value);
+  void (*destroy_value)(void *value, void *user_data);
   /** copy a value */
-  void *(*copy_value)(void *value);
+  void *(*copy_value)(void *value, void *user_data);
 } gpr_avl_vtable;
 
 /** "pointer" to an AVL tree - this is a reference
@@ -53,29 +58,36 @@
   gpr_avl_node *root;
 } gpr_avl;
 
-/** create an immutable AVL tree */
+/** Create an immutable AVL tree. */
 GPRAPI gpr_avl gpr_avl_create(const gpr_avl_vtable *vtable);
-/** add a reference to an existing tree - returns
-    the tree as a convenience */
-GPRAPI gpr_avl gpr_avl_ref(gpr_avl avl);
-/** remove a reference to a tree - destroying it if there
-    are no references left */
-GPRAPI void gpr_avl_unref(gpr_avl avl);
-/** return a new tree with (key, value) added to avl.
+/** Add a reference to an existing tree - returns
+    the tree as a convenience. The optional user_data will be passed to vtable
+    functions. */
+GPRAPI gpr_avl gpr_avl_ref(gpr_avl avl, void *user_data);
+/** Remove a reference to a tree - destroying it if there
+    are no references left. The optional user_data will be passed to vtable
+    functions. */
+GPRAPI void gpr_avl_unref(gpr_avl avl, void *user_data);
+/** Return a new tree with (key, value) added to avl.
     implicitly unrefs avl to allow easy chaining.
     if key exists in avl, the new tree's key entry updated
-    (i.e. a duplicate is not created) */
-GPRAPI gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value);
-/** return a new tree with key deleted
-    implicitly unrefs avl to allow easy chaining. */
-GPRAPI gpr_avl gpr_avl_remove(gpr_avl avl, void *key);
-/** lookup key, and return the associated value.
-    does not mutate avl.
-    returns NULL if key is not found. */
-GPRAPI void *gpr_avl_get(gpr_avl avl, void *key);
+    (i.e. a duplicate is not created). The optional user_data will be passed to
+    vtable functions. */
+GPRAPI gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value,
+                           void *user_data);
+/** Return a new tree with key deleted
+    implicitly unrefs avl to allow easy chaining. The optional user_data will be
+    passed to vtable functions. */
+GPRAPI gpr_avl gpr_avl_remove(gpr_avl avl, void *key, void *user_data);
+/** Lookup key, and return the associated value.
+    Does not mutate avl.
+    Returns NULL if key is not found. The optional user_data will be passed to
+    vtable functions.*/
+GPRAPI void *gpr_avl_get(gpr_avl avl, void *key, void *user_data);
 /** Return 1 if avl contains key, 0 otherwise; if it has the key, sets *value to
-    its value*/
-GPRAPI int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value);
+    its value. THe optional user_data will be passed to vtable functions. */
+GPRAPI int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value,
+                             void *user_data);
 /** Return 1 if avl is empty, 0 otherwise */
 GPRAPI int gpr_avl_is_empty(gpr_avl avl);
 
diff --git a/package.xml b/package.xml
index cfa45f0..9bdebe3 100644
--- a/package.xml
+++ b/package.xml
@@ -158,17 +158,6 @@
     <file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/tmpfile_windows.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" />
-    <file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/support/workaround_list.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer_reader.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" />
@@ -189,7 +178,89 @@
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/support/workaround_list.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/census.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_decoder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_ping.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_rst_stream.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_settings.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_window_update.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_settings.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
+    <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/lib/security/context/security_context.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/fake/fake_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/google_default_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/iam/iam_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/json_token.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_verifier.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/gts_transport_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl_types.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/server/chttp2_server.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_connect_handshaker.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_proxy.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/uri_parser.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_args.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.h" role="src" />
@@ -200,6 +271,7 @@
     <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/stream_compression.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/httpcli.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/parser.h" role="src" />
@@ -222,9 +294,11 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_uv.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/is_epollexclusive_available.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/load_file.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/lockfree_event.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/nameser.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/network_status_tracker.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/pollset.h" role="src" />
@@ -300,85 +374,12 @@
     <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/debug/trace.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_decoder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_ping.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_rst_stream.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_settings.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_window_update.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_settings.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
-    <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/lib/security/context/security_context.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/fake/fake_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/google_default_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/iam/iam_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/json_token.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_verifier.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/ssl_types.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/server/chttp2_server.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/connector.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_connect_handshaker.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_proxy.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_factory.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/uri_parser.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.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/lb_policy/grpclb/client_load_reporting_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/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
-    <file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
-    <file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
-    <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/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" role="src" />
@@ -416,6 +417,7 @@
     <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/compression/stream_compression.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/httpcli.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/parser.c" role="src" />
@@ -537,6 +539,7 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_plugin.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/flow_control.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_ping.c" role="src" />
@@ -584,6 +587,7 @@
     <file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.c" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/gts_transport_security.c" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.c" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security.c" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.c" role="src" />
@@ -615,6 +619,8 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_plugin.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c" role="src" />
diff --git a/setup.py b/setup.py
index e42c834..403c135 100644
--- a/setup.py
+++ b/setup.py
@@ -60,6 +60,18 @@
 
 LICENSE = 'Apache License 2.0'
 
+CLASSIFIERS = [
+    'Development Status :: 5 - Production/Stable',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.4',
+    'Programming Language :: Python :: 3.5',
+    'Programming Language :: Python :: 3.6',
+    'License :: OSI Approved :: Apache Software License',
+],
+
 # Environment variable to determine whether or not the Cython extension should
 # *use* Cython or use the generated C files. Note that this requires the C files
 # to have been generated by building first *with* Cython support. Even if this
@@ -283,6 +295,7 @@
   author_email='grpc-io@googlegroups.com',
   url='https://grpc.io',
   license=LICENSE,
+  classifiers=CLASSIFIERS,
   long_description=open(README).read(),
   ext_modules=CYTHON_EXTENSION_MODULES,
   packages=list(PACKAGES),
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index f8c6fda..b09bf99 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -140,6 +140,7 @@
     printer->Print(vars, "namespace grpc {\n");
     printer->Print(vars, "class CompletionQueue;\n");
     printer->Print(vars, "class Channel;\n");
+    printer->Print(vars, "class RpcService;\n");
     printer->Print(vars, "class ServerCompletionQueue;\n");
     printer->Print(vars, "class ServerContext;\n");
     printer->Print(vars, "}  // namespace grpc\n\n");
@@ -186,21 +187,19 @@
     } else if (ClientOnlyStreaming(method)) {
       printer->Print(
           *vars,
-          "std::unique_ptr< ::grpc::ClientWriterInterface< "
-          "$Request$>>"
+          "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
           " $Method$("
           "::grpc::ClientContext* context, $Response$* response) {\n");
       printer->Indent();
-      printer->Print(*vars,
-                     "return std::unique_ptr< "
-                     "::grpc::ClientWriterInterface< $Request$>>"
-                     "($Method$Raw(context, response));\n");
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
+          "($Method$Raw(context, response));\n");
       printer->Outdent();
       printer->Print("}\n");
       printer->Print(
           *vars,
-          "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< "
-          "$Request$>>"
+          "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
           " Async$Method$(::grpc::ClientContext* context, $Response$* "
           "response, "
           "::grpc::CompletionQueue* cq, void* tag) {\n");
@@ -214,21 +213,19 @@
     } else if (ServerOnlyStreaming(method)) {
       printer->Print(
           *vars,
-          "std::unique_ptr< ::grpc::ClientReaderInterface< "
-          "$Response$>>"
+          "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
           " {\n");
       printer->Indent();
-      printer->Print(*vars,
-                     "return std::unique_ptr< "
-                     "::grpc::ClientReaderInterface< $Response$>>"
-                     "($Method$Raw(context, request));\n");
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
+          "($Method$Raw(context, request));\n");
       printer->Outdent();
       printer->Print("}\n");
       printer->Print(
           *vars,
-          "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< "
-          "$Response$>> "
+          "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
           "Async$Method$("
           "::grpc::ClientContext* context, const $Request$& request, "
           "::grpc::CompletionQueue* cq, void* tag) {\n");
@@ -245,37 +242,36 @@
                      "$Request$, $Response$>> "
                      "$Method$(::grpc::ClientContext* context) {\n");
       printer->Indent();
-      printer->Print(*vars,
-                     "return std::unique_ptr< "
-                     "::grpc::ClientReaderWriterInterface< "
-                     "$Request$, $Response$>>("
-                     "$Method$Raw(context));\n");
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< "
+          "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
+          "$Method$Raw(context));\n");
       printer->Outdent();
       printer->Print("}\n");
-      printer->Print(*vars,
-                     "std::unique_ptr< "
-                     "::grpc::ClientAsyncReaderWriterInterface< "
-                     "$Request$, $Response$>> "
-                     "Async$Method$(::grpc::ClientContext* context, "
-                     "::grpc::CompletionQueue* cq, void* tag) {\n");
+      printer->Print(
+          *vars,
+          "std::unique_ptr< "
+          "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
+          "Async$Method$(::grpc::ClientContext* context, "
+          "::grpc::CompletionQueue* cq, void* tag) {\n");
       printer->Indent();
-      printer->Print(*vars,
-                     "return std::unique_ptr< "
-                     "::grpc::ClientAsyncReaderWriterInterface< "
-                     "$Request$, $Response$>>("
-                     "Async$Method$Raw(context, cq, tag));\n");
+      printer->Print(
+          *vars,
+          "return std::unique_ptr< "
+          "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
+          "Async$Method$Raw(context, cq, tag));\n");
       printer->Outdent();
       printer->Print("}\n");
     }
   } else {
     if (method->NoStreaming()) {
-      printer->Print(*vars,
-                     "virtual "
-                     "::grpc::ClientAsyncResponseReaderInterface< "
-                     "$Response$>* "
-                     "Async$Method$Raw(::grpc::ClientContext* context, "
-                     "const $Request$& request, "
-                     "::grpc::CompletionQueue* cq) = 0;\n");
+      printer->Print(
+          *vars,
+          "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
+          "Async$Method$Raw(::grpc::ClientContext* context, "
+          "const $Request$& request, "
+          "::grpc::CompletionQueue* cq) = 0;\n");
     } else if (ClientOnlyStreaming(method)) {
       printer->Print(
           *vars,
@@ -290,8 +286,7 @@
     } else if (ServerOnlyStreaming(method)) {
       printer->Print(
           *vars,
-          "virtual ::grpc::ClientReaderInterface< $Response$>* "
-          "$Method$Raw("
+          "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
           "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
       printer->Print(
           *vars,
@@ -456,8 +451,7 @@
                                  const grpc_generator::Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
-  printer->Print(*vars,
-                 "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
+  printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
 }
 
 void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
@@ -629,7 +623,7 @@
     printer->Print(*vars,
                    "WithStreamedUnaryMethod_$Method$() {\n"
                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
-                   "    new ::grpc::internal::StreamedUnaryHandler< $Request$, "
+                   "    new ::grpc::StreamedUnaryHandler< $Request$, "
                    "$Response$>(std::bind"
                    "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
                    "Streamed$Method$, this, std::placeholders::_1, "
@@ -677,16 +671,15 @@
         "{}\n");
     printer->Print(" public:\n");
     printer->Indent();
-    printer->Print(
-        *vars,
-        "WithSplitStreamingMethod_$Method$() {\n"
-        "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
-        "    new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
-        "$Response$>(std::bind"
-        "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
-        "Streamed$Method$, this, std::placeholders::_1, "
-        "std::placeholders::_2)));\n"
-        "}\n");
+    printer->Print(*vars,
+                   "WithSplitStreamingMethod_$Method$() {\n"
+                   "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
+                   "    new ::grpc::SplitServerStreamingHandler< $Request$, "
+                   "$Response$>(std::bind"
+                   "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
+                   "Streamed$Method$, this, std::placeholders::_1, "
+                   "std::placeholders::_2)));\n"
+                   "}\n");
     printer->Print(*vars,
                    "~WithSplitStreamingMethod_$Method$() override {\n"
                    "  BaseClassMustBeDerivedFromService(this);\n"
@@ -826,8 +819,7 @@
       " {\n public:\n");
   printer->Indent();
   printer->Print(
-      "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
-      "channel);\n");
+      "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
   for (int i = 0; i < service->method_count(); ++i) {
     PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
   }
@@ -1090,12 +1082,11 @@
                    "::grpc::Status $ns$$Service$::Stub::$Method$("
                    "::grpc::ClientContext* context, "
                    "const $Request$& request, $Response$* response) {\n");
-    printer->Print(
-        *vars,
-        "  return ::grpc::internal::BlockingUnaryCall(channel_.get(), "
-        "rpcmethod_$Method$_, "
-        "context, request, response);\n"
-        "}\n\n");
+    printer->Print(*vars,
+                   "  return ::grpc::BlockingUnaryCall(channel_.get(), "
+                   "rpcmethod_$Method$_, "
+                   "context, request, response);\n"
+                   "}\n\n");
     printer->Print(
         *vars,
         "::grpc::ClientAsyncResponseReader< $Response$>* "
@@ -1104,8 +1095,7 @@
         "::grpc::CompletionQueue* cq) {\n");
     printer->Print(*vars,
                    "  return "
-                   "::grpc::ClientAsyncResponseReader< $Response$>::"
-                   "internal::Create("
+                   "::grpc::ClientAsyncResponseReader< $Response$>::Create("
                    "channel_.get(), cq, "
                    "rpcmethod_$Method$_, "
                    "context, request);\n"
@@ -1115,21 +1105,19 @@
                    "::grpc::ClientWriter< $Request$>* "
                    "$ns$$Service$::Stub::$Method$Raw("
                    "::grpc::ClientContext* context, $Response$* response) {\n");
-    printer->Print(
-        *vars,
-        "  return ::grpc::ClientWriter< $Request$>::internal::Create("
-        "channel_.get(), "
-        "rpcmethod_$Method$_, "
-        "context, response);\n"
-        "}\n\n");
+    printer->Print(*vars,
+                   "  return new ::grpc::ClientWriter< $Request$>("
+                   "channel_.get(), "
+                   "rpcmethod_$Method$_, "
+                   "context, response);\n"
+                   "}\n\n");
     printer->Print(*vars,
                    "::grpc::ClientAsyncWriter< $Request$>* "
                    "$ns$$Service$::Stub::Async$Method$Raw("
                    "::grpc::ClientContext* context, $Response$* response, "
                    "::grpc::CompletionQueue* cq, void* tag) {\n");
     printer->Print(*vars,
-                   "  return ::grpc::ClientAsyncWriter< $Request$>::"
-                   "internal::Create("
+                   "  return ::grpc::ClientAsyncWriter< $Request$>::Create("
                    "channel_.get(), cq, "
                    "rpcmethod_$Method$_, "
                    "context, response, tag);\n"
@@ -1140,21 +1128,19 @@
         "::grpc::ClientReader< $Response$>* "
         "$ns$$Service$::Stub::$Method$Raw("
         "::grpc::ClientContext* context, const $Request$& request) {\n");
-    printer->Print(
-        *vars,
-        "  return ::grpc::ClientReader< $Response$>::internal::Create("
-        "channel_.get(), "
-        "rpcmethod_$Method$_, "
-        "context, request);\n"
-        "}\n\n");
+    printer->Print(*vars,
+                   "  return new ::grpc::ClientReader< $Response$>("
+                   "channel_.get(), "
+                   "rpcmethod_$Method$_, "
+                   "context, request);\n"
+                   "}\n\n");
     printer->Print(*vars,
                    "::grpc::ClientAsyncReader< $Response$>* "
                    "$ns$$Service$::Stub::Async$Method$Raw("
                    "::grpc::ClientContext* context, const $Request$& request, "
                    "::grpc::CompletionQueue* cq, void* tag) {\n");
     printer->Print(*vars,
-                   "  return ::grpc::ClientAsyncReader< $Response$>::"
-                   "internal::Create("
+                   "  return ::grpc::ClientAsyncReader< $Response$>::Create("
                    "channel_.get(), cq, "
                    "rpcmethod_$Method$_, "
                    "context, request, tag);\n"
@@ -1165,8 +1151,8 @@
         "::grpc::ClientReaderWriter< $Request$, $Response$>* "
         "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
     printer->Print(*vars,
-                   "  return ::grpc::ClientReaderWriter< "
-                   "$Request$, $Response$>::internal::Create("
+                   "  return new ::grpc::ClientReaderWriter< "
+                   "$Request$, $Response$>("
                    "channel_.get(), "
                    "rpcmethod_$Method$_, "
                    "context);\n"
@@ -1176,14 +1162,14 @@
         "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
         "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
         "::grpc::CompletionQueue* cq, void* tag) {\n");
-    printer->Print(*vars,
-                   "  return "
-                   "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::"
-                   "internal::Create("
-                   "channel_.get(), cq, "
-                   "rpcmethod_$Method$_, "
-                   "context, tag);\n"
-                   "}\n\n");
+    printer->Print(
+        *vars,
+        "  return "
+        "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::Create("
+        "channel_.get(), cq, "
+        "rpcmethod_$Method$_, "
+        "context, tag);\n"
+        "}\n\n");
   }
 }
 
@@ -1293,7 +1279,7 @@
     printer->Print(*vars,
                    ", rpcmethod_$Method$_("
                    "$prefix$$Service$_method_names[$Idx$], "
-                   "::grpc::internal::RpcMethod::$StreamingType$, "
+                   "::grpc::RpcMethod::$StreamingType$, "
                    "channel"
                    ")\n");
   }
@@ -1316,38 +1302,38 @@
     if (method->NoStreaming()) {
       printer->Print(
           *vars,
-          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "AddMethod(new ::grpc::RpcServiceMethod(\n"
           "    $prefix$$Service$_method_names[$Idx$],\n"
-          "    ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
-          "    new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
+          "    ::grpc::RpcMethod::NORMAL_RPC,\n"
+          "    new ::grpc::RpcMethodHandler< $ns$$Service$::Service, "
           "$Request$, "
           "$Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
     } else if (ClientOnlyStreaming(method.get())) {
       printer->Print(
           *vars,
-          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "AddMethod(new ::grpc::RpcServiceMethod(\n"
           "    $prefix$$Service$_method_names[$Idx$],\n"
-          "    ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
-          "    new ::grpc::internal::ClientStreamingHandler< "
+          "    ::grpc::RpcMethod::CLIENT_STREAMING,\n"
+          "    new ::grpc::ClientStreamingHandler< "
           "$ns$$Service$::Service, $Request$, $Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
     } else if (ServerOnlyStreaming(method.get())) {
       printer->Print(
           *vars,
-          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "AddMethod(new ::grpc::RpcServiceMethod(\n"
           "    $prefix$$Service$_method_names[$Idx$],\n"
-          "    ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
-          "    new ::grpc::internal::ServerStreamingHandler< "
+          "    ::grpc::RpcMethod::SERVER_STREAMING,\n"
+          "    new ::grpc::ServerStreamingHandler< "
           "$ns$$Service$::Service, $Request$, $Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
     } else if (method->BidiStreaming()) {
       printer->Print(
           *vars,
-          "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+          "AddMethod(new ::grpc::RpcServiceMethod(\n"
           "    $prefix$$Service$_method_names[$Idx$],\n"
-          "    ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
-          "    new ::grpc::internal::BidiStreamingHandler< "
+          "    ::grpc::RpcMethod::BIDI_STREAMING,\n"
+          "    new ::grpc::BidiStreamingHandler< "
           "$ns$$Service$::Service, $Request$, $Response$>(\n"
           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
     }
@@ -1515,8 +1501,7 @@
     printer->Print(
         *vars,
         "MOCK_METHOD3(Async$Method$Raw, "
-        "::grpc::ClientAsyncReaderWriterInterface<$Request$, "
-        "$Response$>*"
+        "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
         "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, "
         "void* tag));\n");
   }
diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc
index 249ba08..c0fef91 100644
--- a/src/compiler/node_generator.cc
+++ b/src/compiler/node_generator.cc
@@ -47,6 +47,7 @@
   grpc::string basename = grpc_generator::StripProto(filename);
   basename = grpc_generator::StringReplace(basename, "-", "$");
   basename = grpc_generator::StringReplace(basename, "/", "_");
+  basename = grpc_generator::StringReplace(basename, ".", "_");
   return basename + "_pb";
 }
 
diff --git a/src/compiler/php_generator.cc b/src/compiler/php_generator.cc
index 6d34761..38ec46e 100644
--- a/src/compiler/php_generator.cc
+++ b/src/compiler/php_generator.cc
@@ -97,13 +97,14 @@
 }
 
 // Prints out the service descriptor object
-void PrintService(const ServiceDescriptor *service, Printer *out) {
+void PrintService(const ServiceDescriptor *service,
+                  const grpc::string &parameter, Printer *out) {
   map<grpc::string, grpc::string> vars;
   out->Print("/**\n");
   out->Print(GetPHPComments(service, " *").c_str());
   out->Print(" */\n");
-  vars["name"] = service->name();
-  out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
+  vars["name"] = GetPHPServiceClassname(service, parameter);
+  out->Print(vars, "class $name$ extends \\Grpc\\BaseStub {\n\n");
   out->Indent();
   out->Indent();
   out->Print(
@@ -131,7 +132,8 @@
 }
 
 grpc::string GenerateFile(const FileDescriptor *file,
-                          const ServiceDescriptor *service) {
+                          const ServiceDescriptor *service,
+                          const grpc::string &parameter) {
   grpc::string output;
   {
     StringOutputStream output_stream(&output);
@@ -150,7 +152,7 @@
     vars["package"] = MessageIdentifierName(file->package());
     out.Print(vars, "namespace $package$;\n\n");
 
-    PrintService(service, &out);
+    PrintService(service, parameter, &out);
   }
   return output;
 }
diff --git a/src/compiler/php_generator.h b/src/compiler/php_generator.h
index 4518bc2..9a04bd3 100644
--- a/src/compiler/php_generator.h
+++ b/src/compiler/php_generator.h
@@ -24,7 +24,8 @@
 namespace grpc_php_generator {
 
 grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file,
-                          const grpc::protobuf::ServiceDescriptor *service);
+                          const grpc::protobuf::ServiceDescriptor *service,
+                          const grpc::string &parameter);
 
 }  // namespace grpc_php_generator
 
diff --git a/src/compiler/php_generator_helpers.h b/src/compiler/php_generator_helpers.h
index 3a5c08b..5edebf6 100644
--- a/src/compiler/php_generator_helpers.h
+++ b/src/compiler/php_generator_helpers.h
@@ -26,9 +26,22 @@
 
 namespace grpc_php_generator {
 
+inline grpc::string GetPHPServiceClassname(
+    const grpc::protobuf::ServiceDescriptor *service,
+    const grpc::string &parameter) {
+  grpc::string suffix;
+  if (parameter == "") {
+    suffix = "Client";
+  } else {
+    suffix = parameter;
+  }
+  return service->name() + suffix;
+}
+
 inline grpc::string GetPHPServiceFilename(
     const grpc::protobuf::FileDescriptor *file,
-    const grpc::protobuf::ServiceDescriptor *service) {
+    const grpc::protobuf::ServiceDescriptor *service,
+    const grpc::string &parameter) {
   std::vector<grpc::string> tokens =
       grpc_generator::tokenize(file->package(), ".");
   std::ostringstream oss;
@@ -36,7 +49,7 @@
     oss << (i == 0 ? "" : "/")
         << grpc_generator::CapitalizeFirstLetter(tokens[i]);
   }
-  return oss.str() + "/" + service->name() + "Client.php";
+  return oss.str() + "/" + GetPHPServiceClassname(service, parameter) + ".php";
 }
 
 // ReplaceAll replaces all instances of search with replace in s.
diff --git a/src/compiler/php_plugin.cc b/src/compiler/php_plugin.cc
index 7a581fd..bbe9165 100644
--- a/src/compiler/php_plugin.cc
+++ b/src/compiler/php_plugin.cc
@@ -41,10 +41,11 @@
     }
 
     for (int i = 0; i < file->service_count(); i++) {
-      grpc::string code = GenerateFile(file, file->service(i));
+      grpc::string code = GenerateFile(file, file->service(i), parameter);
 
       // Get output file name
-      grpc::string file_name = GetPHPServiceFilename(file, file->service(i));
+      grpc::string file_name =
+          GetPHPServiceFilename(file, file->service(i), parameter);
 
       std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
           context->Open(file_name));
diff --git a/src/core/ext/filters/client_channel/OWNERS b/src/core/ext/filters/client_channel/OWNERS
new file mode 100644
index 0000000..773bc73
--- /dev/null
+++ b/src/core/ext/filters/client_channel/OWNERS
@@ -0,0 +1,4 @@
+set noparent
+@markdroth
+@dgquintas
+@ctiller
diff --git a/src/core/ext/filters/client_channel/channel_connectivity.c b/src/core/ext/filters/client_channel/channel_connectivity.c
index c3dca14..b83c952 100644
--- a/src/core/ext/filters/client_channel/channel_connectivity.c
+++ b/src/core/ext/filters/client_channel/channel_connectivity.c
@@ -208,7 +208,7 @@
       7, (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec,
           (int)deadline.clock_type, cq, tag));
 
-  grpc_cq_begin_op(cq, tag);
+  GPR_ASSERT(grpc_cq_begin_op(cq, tag));
 
   gpr_mu_init(&w->mu);
   GRPC_CLOSURE_INIT(&w->on_complete, watch_complete, w,
diff --git a/src/core/ext/filters/client_channel/client_channel.c b/src/core/ext/filters/client_channel/client_channel.c
index 7add432..58e31d7 100644
--- a/src/core/ext/filters/client_channel/client_channel.c
+++ b/src/core/ext/filters/client_channel/client_channel.c
@@ -52,7 +52,8 @@
 
 /* Client channel implementation */
 
-grpc_tracer_flag grpc_client_channel_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_client_channel_trace =
+    GRPC_TRACER_INITIALIZER(false, "client_channel");
 
 /*************************************************************************
  * METHOD-CONFIG TABLE
@@ -370,6 +371,7 @@
             grpc_error_string(error));
   }
   // Extract the following fields from the resolver result, if non-NULL.
+  bool lb_policy_updated = false;
   char *lb_policy_name = NULL;
   bool lb_policy_name_changed = false;
   grpc_lb_policy *new_lb_policy = NULL;
@@ -424,6 +426,7 @@
         strcmp(chand->info_lb_policy_name, lb_policy_name) != 0;
     if (chand->lb_policy != NULL && !lb_policy_name_changed) {
       // Continue using the same LB policy.  Update with new addresses.
+      lb_policy_updated = true;
       grpc_lb_policy_update_locked(exec_ctx, chand->lb_policy, &lb_policy_args);
     } else {
       // Instantiate new LB policy.
@@ -569,8 +572,11 @@
       }
       watch_lb_policy_locked(exec_ctx, chand, new_lb_policy, state);
     }
-    set_channel_connectivity_state_locked(
-        exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
+    if (!lb_policy_updated) {
+      set_channel_connectivity_state_locked(exec_ctx, chand, state,
+                                            GRPC_ERROR_REF(state_error),
+                                            "new_lb+resolver");
+    }
     grpc_resolver_next_locked(exec_ctx, chand->resolver,
                               &chand->resolver_result,
                               &chand->on_resolver_result_changed);
diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.c b/src/core/ext/filters/client_channel/client_channel_plugin.c
index 6f133a6..c32e83d 100644
--- a/src/core/ext/filters/client_channel/client_channel_plugin.c
+++ b/src/core/ext/filters/client_channel/client_channel_plugin.c
@@ -78,9 +78,9 @@
       GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
       (void *)&grpc_client_channel_filter);
   grpc_http_connect_register_handshaker_factory();
-  grpc_register_tracer("client_channel", &grpc_client_channel_trace);
+  grpc_register_tracer(&grpc_client_channel_trace);
 #ifndef NDEBUG
-  grpc_register_tracer("resolver_refcount", &grpc_trace_resolver_refcount);
+  grpc_register_tracer(&grpc_trace_resolver_refcount);
 #endif
 }
 
diff --git a/src/core/ext/filters/client_channel/http_proxy.c b/src/core/ext/filters/client_channel/http_proxy.c
index cfb5ec6..ef3512e 100644
--- a/src/core/ext/filters/client_channel/http_proxy.c
+++ b/src/core/ext/filters/client_channel/http_proxy.c
@@ -22,6 +22,7 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
@@ -29,14 +30,23 @@
 #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/filters/client_channel/uri_parser.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/b64.h"
 #include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
 
-static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) {
+/**
+ * Parses the 'http_proxy' env var and returns the proxy hostname to resolve or
+ * NULL on error. Also sets 'user_cred' to user credentials if present in the
+ * 'http_proxy' env var, otherwise leaves it unchanged. It is caller's
+ * responsibility to gpr_free user_cred.
+ */
+static char* get_http_proxy_server(grpc_exec_ctx* exec_ctx, char** user_cred) {
+  GPR_ASSERT(user_cred != NULL);
+  char* proxy_name = NULL;
   char* uri_str = gpr_getenv("http_proxy");
   if (uri_str == NULL) return NULL;
   grpc_uri* uri =
       grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */);
-  char* proxy_name = NULL;
   if (uri == NULL || uri->authority == NULL) {
     gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
     goto done;
@@ -45,11 +55,27 @@
     gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme);
     goto done;
   }
-  if (strchr(uri->authority, '@') != NULL) {
-    gpr_log(GPR_ERROR, "userinfo not supported in proxy URI");
-    goto done;
+  /* Split on '@' to separate user credentials from host */
+  char** authority_strs = NULL;
+  size_t authority_nstrs;
+  gpr_string_split(uri->authority, "@", &authority_strs, &authority_nstrs);
+  GPR_ASSERT(authority_nstrs != 0); /* should have at least 1 string */
+  if (authority_nstrs == 1) {
+    /* User cred not present in authority */
+    proxy_name = authority_strs[0];
+  } else if (authority_nstrs == 2) {
+    /* User cred found */
+    *user_cred = authority_strs[0];
+    proxy_name = authority_strs[1];
+    gpr_log(GPR_DEBUG, "userinfo found in proxy URI");
+  } else {
+    /* Bad authority */
+    for (size_t i = 0; i < authority_nstrs; i++) {
+      gpr_free(authority_strs[i]);
+    }
+    proxy_name = NULL;
   }
-  proxy_name = gpr_strdup(uri->authority);
+  gpr_free(authority_strs);
 done:
   gpr_free(uri_str);
   grpc_uri_destroy(uri);
@@ -62,7 +88,8 @@
                                   const grpc_channel_args* args,
                                   char** name_to_resolve,
                                   grpc_channel_args** new_args) {
-  *name_to_resolve = grpc_get_http_proxy_server(exec_ctx);
+  char* user_cred = NULL;
+  *name_to_resolve = get_http_proxy_server(exec_ctx, &user_cred);
   if (*name_to_resolve == NULL) return false;
   grpc_uri* uri =
       grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */);
@@ -71,19 +98,82 @@
             "'http_proxy' environment variable set, but cannot "
             "parse server URI '%s' -- not using proxy",
             server_uri);
-    if (uri != NULL) grpc_uri_destroy(uri);
+    if (uri != NULL) {
+      gpr_free(user_cred);
+      grpc_uri_destroy(uri);
+    }
     return false;
   }
   if (strcmp(uri->scheme, "unix") == 0) {
     gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'",
             server_uri);
+    gpr_free(user_cred);
     grpc_uri_destroy(uri);
     return false;
   }
-  grpc_arg new_arg = grpc_channel_arg_string_create(
+  char* no_proxy_str = gpr_getenv("no_proxy");
+  if (no_proxy_str != NULL) {
+    static const char* NO_PROXY_SEPARATOR = ",";
+    bool use_proxy = true;
+    char* server_host;
+    char* server_port;
+    if (!gpr_split_host_port(uri->path[0] == '/' ? uri->path + 1 : uri->path,
+                             &server_host, &server_port)) {
+      gpr_log(GPR_INFO,
+              "unable to split host and port, not checking no_proxy list for "
+              "host '%s'",
+              server_uri);
+    } else {
+      size_t uri_len = strlen(server_host);
+      char** no_proxy_hosts;
+      size_t num_no_proxy_hosts;
+      gpr_string_split(no_proxy_str, NO_PROXY_SEPARATOR, &no_proxy_hosts,
+                       &num_no_proxy_hosts);
+      for (size_t i = 0; i < num_no_proxy_hosts; i++) {
+        char* no_proxy_entry = no_proxy_hosts[i];
+        size_t no_proxy_len = strlen(no_proxy_entry);
+        if (no_proxy_len <= uri_len &&
+            gpr_stricmp(no_proxy_entry, &server_host[uri_len - no_proxy_len]) ==
+                0) {
+          gpr_log(GPR_INFO, "not using proxy for host in no_proxy list '%s'",
+                  server_uri);
+          use_proxy = false;
+          break;
+        }
+      }
+      for (size_t i = 0; i < num_no_proxy_hosts; i++) {
+        gpr_free(no_proxy_hosts[i]);
+      }
+      gpr_free(no_proxy_hosts);
+      gpr_free(server_host);
+      gpr_free(server_port);
+      if (!use_proxy) {
+        grpc_uri_destroy(uri);
+        gpr_free(*name_to_resolve);
+        *name_to_resolve = NULL;
+        return false;
+      }
+    }
+  }
+  grpc_arg args_to_add[2];
+  args_to_add[0] = grpc_channel_arg_string_create(
       GRPC_ARG_HTTP_CONNECT_SERVER,
       uri->path[0] == '/' ? uri->path + 1 : uri->path);
-  *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
+  if (user_cred != NULL) {
+    /* Use base64 encoding for user credentials as stated in RFC 7617 */
+    char* encoded_user_cred =
+        grpc_base64_encode(user_cred, strlen(user_cred), 0, 0);
+    char* header;
+    gpr_asprintf(&header, "Proxy-Authorization:Basic %s", encoded_user_cred);
+    gpr_free(encoded_user_cred);
+    args_to_add[1] =
+        grpc_channel_arg_string_create(GRPC_ARG_HTTP_CONNECT_HEADERS, header);
+    *new_args = grpc_channel_args_copy_and_add(args, args_to_add, 2);
+    gpr_free(header);
+  } else {
+    *new_args = grpc_channel_args_copy_and_add(args, args_to_add, 1);
+  }
+  gpr_free(user_cred);
   grpc_uri_destroy(uri);
   return true;
 }
diff --git a/src/core/ext/filters/client_channel/lb_policy.c b/src/core/ext/filters/client_channel/lb_policy.c
index 8d69ba6..dd95a13 100644
--- a/src/core/ext/filters/client_channel/lb_policy.c
+++ b/src/core/ext/filters/client_channel/lb_policy.c
@@ -22,7 +22,8 @@
 #define WEAK_REF_BITS 16
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_lb_policy_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_lb_policy_refcount =
+    GRPC_TRACER_INITIALIZER(false, "lb_policy_refcount");
 #endif
 
 void grpc_lb_policy_init(grpc_lb_policy *policy,
@@ -53,7 +54,7 @@
 #ifndef NDEBUG
   if (GRPC_TRACER_ON(grpc_trace_lb_policy_refcount)) {
     gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-            "LB_POLICY: 0x%p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
+            "LB_POLICY: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
             purpose, old_val, old_val + delta, reason);
   }
 #endif
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c
index 52c6e38..568bb2b 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c
@@ -88,7 +88,6 @@
   // Record call finished, optionally setting client_failed_to_send and
   // received.
   grpc_grpclb_client_stats_add_call_finished(
-      false /* drop_for_rate_limiting */, false /* drop_for_load_balancing */,
       !calld->send_initial_metadata_succeeded /* client_failed_to_send */,
       calld->recv_initial_metadata_succeeded /* known_received */,
       calld->client_stats);
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
index 5a5ff29..bb9217d 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
@@ -123,7 +123,7 @@
 #define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
 #define GRPC_GRPCLB_RECONNECT_JITTER 0.2
 
-grpc_tracer_flag grpc_lb_glb_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_lb_glb_trace = GRPC_TRACER_INITIALIZER(false, "glb");
 
 /* add lb_token of selected subchannel (address) to the call's initial
  * metadata */
@@ -416,9 +416,7 @@
 
 static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
                             bool log) {
-  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
-    return false;
-  }
+  if (server->drop) return false;
   const grpc_grpclb_ip_address *ip = &server->ip_address;
   if (server->port >> 16 != 0) {
     if (log) {
@@ -462,7 +460,7 @@
 static void parse_server(const grpc_grpclb_server *server,
                          grpc_resolved_address *addr) {
   memset(addr, 0, sizeof(*addr));
-  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) return;
+  if (server->drop) return;
   const uint16_t netorder_port = htons((uint16_t)server->port);
   /* the addresses are given in binary format (a in(6)_addr struct) in
    * server->ip_address.bytes. */
@@ -491,11 +489,8 @@
   for (size_t i = 0; i < serverlist->num_servers; ++i) {
     if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
   }
-  if (num_valid == 0) return NULL;
-
   grpc_lb_addresses *lb_addresses =
       grpc_lb_addresses_create(num_valid, &lb_token_vtable);
-
   /* second pass: actually populate the addresses and LB tokens (aka user data
    * to the outside world) to be read by the RR policy during its creation.
    * Given that the validity tests are very cheap, they are performed again
@@ -503,14 +498,12 @@
    * incurr in an allocation due to the arbitrary number of server */
   size_t addr_idx = 0;
   for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
-    GPR_ASSERT(addr_idx < num_valid);
     const grpc_grpclb_server *server = serverlist->servers[sl_idx];
     if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
-
+    GPR_ASSERT(addr_idx < num_valid);
     /* address processing */
     grpc_resolved_address addr;
     parse_server(server, &addr);
-
     /* lb token processing */
     void *user_data;
     if (server->has_load_balance_token) {
@@ -596,7 +589,7 @@
         grpc_connectivity_state_name(rr_state), (void *)glb_policy->rr_policy);
   }
   grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, rr_state,
-                              GRPC_ERROR_REF(rr_state_error),
+                              rr_state_error,
                               "update_lb_connectivity_status_locked");
 }
 
@@ -615,7 +608,7 @@
   if (glb_policy->serverlist_index == glb_policy->serverlist->num_servers) {
     glb_policy->serverlist_index = 0;  // Wrap-around.
   }
-  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
+  if (server->drop) {
     // Not using the RR policy, so unref it.
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
       gpr_log(GPR_INFO, "Unreffing RR for drop (0x%" PRIxPTR ")",
@@ -627,11 +620,8 @@
     // the client_load_reporting filter, because we do not create a
     // subchannel call (and therefore no client_load_reporting filter)
     // for dropped calls.
-    grpc_grpclb_client_stats_add_call_started(wc_arg->client_stats);
-    grpc_grpclb_client_stats_add_call_finished(
-        server->drop_for_rate_limiting, server->drop_for_load_balancing,
-        false /* failed_to_send */, false /* known_received */,
-        wc_arg->client_stats);
+    grpc_grpclb_client_stats_add_call_dropped_locked(server->load_balance_token,
+                                                     wc_arg->client_stats);
     grpc_grpclb_client_stats_unref(wc_arg->client_stats);
     if (force_async) {
       GPR_ASSERT(wc_arg->wrapped_closure != NULL);
@@ -678,11 +668,12 @@
 
 static grpc_lb_policy_args *lb_policy_args_create(grpc_exec_ctx *exec_ctx,
                                                   glb_lb_policy *glb_policy) {
+  grpc_lb_addresses *addresses =
+      process_serverlist_locked(exec_ctx, glb_policy->serverlist);
+  GPR_ASSERT(addresses != NULL);
   grpc_lb_policy_args *args = gpr_zalloc(sizeof(*args));
   args->client_channel_factory = glb_policy->cc_factory;
   args->combiner = glb_policy->base.combiner;
-  grpc_lb_addresses *addresses =
-      process_serverlist_locked(exec_ctx, glb_policy->serverlist);
   // 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};
@@ -719,7 +710,6 @@
     return;
   }
   glb_policy->rr_policy = new_rr_policy;
-
   grpc_error *rr_state_error = NULL;
   const grpc_connectivity_state rr_state =
       grpc_lb_policy_check_connectivity_locked(exec_ctx, glb_policy->rr_policy,
@@ -727,7 +717,6 @@
   /* Connectivity state is a function of the RR policy updated/created */
   update_lb_connectivity_status_locked(exec_ctx, glb_policy, rr_state,
                                        rr_state_error);
-
   /* Add the gRPC LB's interested_parties pollset_set to that of the newly
    * created RR policy. This will make the RR policy progress upon activity on
    * gRPC LB, which in turn is tied to the application's call */
@@ -746,7 +735,7 @@
   rr_connectivity->state = rr_state;
 
   /* Subscribe to changes to the connectivity of the new RR */
-  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_sched");
+  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "glb_rr_connectivity_cb");
   grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
                                                &rr_connectivity->state,
                                                &rr_connectivity->on_change);
@@ -761,8 +750,8 @@
     pp->wrapped_on_complete_arg.client_stats =
         grpc_grpclb_client_stats_ref(glb_policy->client_stats);
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
-      gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
-              (intptr_t)glb_policy->rr_policy);
+      gpr_log(GPR_INFO, "Pending pick about to (async) PICK from %p",
+              (void *)glb_policy->rr_policy);
     }
     pick_from_internal_rr_locked(exec_ctx, glb_policy, &pp->pick_args,
                                  true /* force_async */, pp->target,
@@ -788,10 +777,9 @@
                                glb_lb_policy *glb_policy) {
   GPR_ASSERT(glb_policy->serverlist != NULL &&
              glb_policy->serverlist->num_servers > 0);
-
   if (glb_policy->shutting_down) return;
-
   grpc_lb_policy_args *args = lb_policy_args_create(exec_ctx, glb_policy);
+  GPR_ASSERT(args != NULL);
   if (glb_policy->rr_policy != NULL) {
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
       gpr_log(GPR_DEBUG, "Updating Round Robin policy (%p)",
@@ -812,32 +800,31 @@
                                                void *arg, grpc_error *error) {
   rr_connectivity_data *rr_connectivity = arg;
   glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
-
-  const bool shutting_down = glb_policy->shutting_down;
-  bool unref_needed = false;
-  GRPC_ERROR_REF(error);
-
-  if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
-    /* RR policy shutting down. Don't renew subscription and free the arg of
-     * this callback. In addition  we need to stash away the current policy to
-     * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
-     * one, the policy would be destroyed, alongside the lock, which would
-     * result in a use-after-free */
-    unref_needed = true;
-    gpr_free(rr_connectivity);
-  } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
-    update_lb_connectivity_status_locked(exec_ctx, glb_policy,
-                                         rr_connectivity->state, error);
-    /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
-    grpc_lb_policy_notify_on_state_change_locked(
-        exec_ctx, glb_policy->rr_policy, &rr_connectivity->state,
-        &rr_connectivity->on_change);
-  }
-  if (unref_needed) {
+  if (glb_policy->shutting_down) {
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
-                              "rr_connectivity_cb");
+                              "glb_rr_connectivity_cb");
+    gpr_free(rr_connectivity);
+    return;
   }
-  GRPC_ERROR_UNREF(error);
+  if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN) {
+    /* An RR policy that has transitioned into the SHUTDOWN connectivity state
+     * should not be considered for picks or updates: the SHUTDOWN state is a
+     * sink, policies can't transition back from it. .*/
+    GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy,
+                         "rr_connectivity_shutdown");
+    glb_policy->rr_policy = NULL;
+    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
+                              "glb_rr_connectivity_cb");
+    gpr_free(rr_connectivity);
+    return;
+  }
+  /* rr state != SHUTDOWN && !glb_policy->shutting down: biz as usual */
+  update_lb_connectivity_status_locked(
+      exec_ctx, glb_policy, rr_connectivity->state, GRPC_ERROR_REF(error));
+  /* Resubscribe. Reuse the "glb_rr_connectivity_cb" weak ref. */
+  grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
+                                               &rr_connectivity->state,
+                                               &rr_connectivity->on_change);
 }
 
 static void destroy_balancer_name(grpc_exec_ctx *exec_ctx,
@@ -1001,7 +988,6 @@
     gpr_free(glb_policy);
     return NULL;
   }
-
   GRPC_CLOSURE_INIT(&glb_policy->lb_channel_on_connectivity_changed,
                     glb_lb_channel_on_connectivity_changed_cb, glb_policy,
                     grpc_combiner_scheduler(args->combiner));
@@ -1058,7 +1044,7 @@
   glb_policy->pending_picks = NULL;
   pending_ping *pping = glb_policy->pending_pings;
   glb_policy->pending_pings = NULL;
-  if (glb_policy->rr_policy) {
+  if (glb_policy->rr_policy != NULL) {
     GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
   }
   // We destroy the LB channel here because
@@ -1089,6 +1075,16 @@
   }
 }
 
+// Cancel a specific pending pick.
+//
+// A grpclb pick progresses as follows:
+// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
+//   handed over to the RR policy (in create_rr_locked()). From that point
+//   onwards, it'll be RR's responsibility. For cancellations, that implies the
+//   pick needs also be cancelled by the RR instance.
+// - Otherwise, without an RR instance, picks stay pending at this policy's
+//   level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
+//   we invoke the completion closure and set *target to NULL right here.
 static void glb_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
                                    grpc_connected_subchannel **target,
                                    grpc_error *error) {
@@ -1108,9 +1104,23 @@
     }
     pp = next;
   }
+  if (glb_policy->rr_policy != NULL) {
+    grpc_lb_policy_cancel_pick_locked(exec_ctx, glb_policy->rr_policy, target,
+                                      GRPC_ERROR_REF(error));
+  }
   GRPC_ERROR_UNREF(error);
 }
 
+// Cancel all pending picks.
+//
+// A grpclb pick progresses as follows:
+// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
+//   handed over to the RR policy (in create_rr_locked()). From that point
+//   onwards, it'll be RR's responsibility. For cancellations, that implies the
+//   pick needs also be cancelled by the RR instance.
+// - Otherwise, without an RR instance, picks stay pending at this policy's
+//   level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
+//   we invoke the completion closure and set *target to NULL right here.
 static void glb_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
                                     grpc_lb_policy *pol,
                                     uint32_t initial_metadata_flags_mask,
@@ -1132,6 +1142,11 @@
     }
     pp = next;
   }
+  if (glb_policy->rr_policy != NULL) {
+    grpc_lb_policy_cancel_picks_locked(
+        exec_ctx, glb_policy->rr_policy, initial_metadata_flags_mask,
+        initial_metadata_flags_eq, GRPC_ERROR_REF(error));
+  }
   GRPC_ERROR_UNREF(error);
 }
 
@@ -1286,15 +1301,14 @@
 }
 
 static bool load_report_counters_are_zero(grpc_grpclb_request *request) {
+  grpc_grpclb_dropped_call_counts *drop_entries =
+      request->client_stats.calls_finished_with_drop.arg;
   return request->client_stats.num_calls_started == 0 &&
          request->client_stats.num_calls_finished == 0 &&
-         request->client_stats.num_calls_finished_with_drop_for_rate_limiting ==
-             0 &&
-         request->client_stats
-                 .num_calls_finished_with_drop_for_load_balancing == 0 &&
          request->client_stats.num_calls_finished_with_client_failed_to_send ==
              0 &&
-         request->client_stats.num_calls_finished_known_received == 0;
+         request->client_stats.num_calls_finished_known_received == 0 &&
+         (drop_entries == NULL || drop_entries->num_entries == 0);
 }
 
 static void send_client_load_report_locked(grpc_exec_ctx *exec_ctx, void *arg,
@@ -1309,7 +1323,7 @@
   // Construct message payload.
   GPR_ASSERT(glb_policy->client_load_report_payload == NULL);
   grpc_grpclb_request *request =
-      grpc_grpclb_load_report_request_create(glb_policy->client_stats);
+      grpc_grpclb_load_report_request_create_locked(glb_policy->client_stats);
   // Skip client load report if the counters were all zero in the last
   // report and they are still zero in this one.
   if (load_report_counters_are_zero(request)) {
@@ -1463,7 +1477,8 @@
   op++;
   /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
    * count goes to zero) to be unref'd in lb_on_sent_initial_request_locked() */
-  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
+  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base,
+                          "lb_on_sent_initial_request_locked");
   call_error = grpc_call_start_batch_and_execute(
       exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
       &glb_policy->lb_on_sent_initial_request);
@@ -1480,8 +1495,9 @@
   op->reserved = NULL;
   op++;
   /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
-   * count goes to zero) to be unref'd in lb_on_server_status_received */
-  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
+   * count goes to zero) to be unref'd in lb_on_server_status_received_locked */
+  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base,
+                          "lb_on_server_status_received_locked");
   call_error = grpc_call_start_batch_and_execute(
       exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
       &glb_policy->lb_on_server_status_received);
@@ -1493,8 +1509,9 @@
   op->flags = 0;
   op->reserved = NULL;
   op++;
-  /* take another weak ref to be unref'd in lb_on_response_received */
-  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received");
+  /* take another weak ref to be unref'd/reused in
+   * lb_on_response_received_locked */
+  GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received_locked");
   call_error = grpc_call_start_batch_and_execute(
       exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
       &glb_policy->lb_on_response_received);
@@ -1511,13 +1528,12 @@
     do_send_client_load_report_locked(exec_ctx, glb_policy);
   }
   GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
-                            "lb_on_response_received_locked");
+                            "lb_on_sent_initial_request_locked");
 }
 
 static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
                                            grpc_error *error) {
   glb_lb_policy *glb_policy = arg;
-
   grpc_op ops[2];
   memset(ops, 0, sizeof(ops));
   grpc_op *op = ops;
@@ -1548,7 +1564,7 @@
         }
         /* take a weak ref (won't prevent calling of \a glb_shutdown() if the
          * strong ref count goes to zero) to be unref'd in
-         * send_client_load_report() */
+         * send_client_load_report_locked() */
         glb_policy->client_load_report_timer_pending = true;
         GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "client_load_report");
         schedule_next_client_load_report(exec_ctx, glb_policy);
@@ -1576,7 +1592,6 @@
             gpr_free(ipport);
           }
         }
-
         /* update serverlist */
         if (serverlist->num_servers > 0) {
           if (grpc_grpclb_serverlist_equals(glb_policy->serverlist,
@@ -1611,9 +1626,7 @@
                 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
       }
     }
-
     grpc_slice_unref_internal(exec_ctx, response_slice);
-
     if (!glb_policy->shutting_down) {
       /* keep listening for serverlist updates */
       op->op = GRPC_OP_RECV_MESSAGE;
@@ -1621,7 +1634,7 @@
       op->flags = 0;
       op->reserved = NULL;
       op++;
-      /* reuse the "lb_on_response_received" weak ref taken in
+      /* reuse the "lb_on_response_received_locked" weak ref taken in
        * query_for_backends_locked() */
       const grpc_call_error call_error = grpc_call_start_batch_and_execute(
           exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
@@ -1629,10 +1642,10 @@
       GPR_ASSERT(GRPC_CALL_OK == call_error);
     }
   } else { /* empty payload: call cancelled. */
-           /* dispose of the "lb_on_response_received" weak ref taken in
+           /* dispose of the "lb_on_response_received_locked" weak ref taken in
             * query_for_backends_locked() and reused in every reception loop */
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
-                              "lb_on_response_received_empty_payload");
+                              "lb_on_response_received_locked_empty_payload");
   }
 }
 
@@ -1699,13 +1712,12 @@
                     &glb_policy->lb_on_call_retry, now);
   }
   GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
-                            "lb_on_server_status_received");
+                            "lb_on_server_status_received_locked");
 }
 
 static void glb_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
                               const grpc_lb_policy_args *args) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)policy;
-
   if (glb_policy->updating_lb_channel) {
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
       gpr_log(GPR_INFO,
@@ -1757,7 +1769,8 @@
 
   if (!glb_policy->watching_lb_channel) {
     // Watch the LB channel connectivity for connection.
-    glb_policy->lb_channel_connectivity = GRPC_CHANNEL_INIT;
+    glb_policy->lb_channel_connectivity = grpc_channel_check_connectivity_state(
+        glb_policy->lb_channel, true /* try to connect */);
     grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
         grpc_channel_get_channel_stack(glb_policy->lb_channel));
     GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
@@ -1813,9 +1826,11 @@
         // lb_on_server_status_received will pick up the cancel and reinit
         // lb_call.
         if (glb_policy->pending_update_args != NULL) {
-          const grpc_lb_policy_args *args = glb_policy->pending_update_args;
+          grpc_lb_policy_args *args = glb_policy->pending_update_args;
           glb_policy->pending_update_args = NULL;
           glb_update_locked(exec_ctx, &glb_policy->base, args);
+          grpc_channel_args_destroy(exec_ctx, args->args);
+          gpr_free(args);
         }
       } else if (glb_policy->started_picking && !glb_policy->shutting_down) {
         if (glb_policy->retry_timer_active) {
@@ -1879,9 +1894,9 @@
 
 void grpc_lb_policy_grpclb_init() {
   grpc_register_lb_policy(grpc_glb_lb_factory_create());
-  grpc_register_tracer("glb", &grpc_lb_glb_trace);
+  grpc_register_tracer(&grpc_lb_glb_trace);
 #ifndef NDEBUG
-  grpc_register_tracer("lb_policy_refcount", &grpc_trace_lb_policy_refcount);
+  grpc_register_tracer(&grpc_trace_lb_policy_refcount);
 #endif
   grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c
index c762443..5b62623 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c
@@ -18,8 +18,11 @@
 
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
 
+#include <string.h>
+
 #include <grpc/support/alloc.h>
 #include <grpc/support/atm.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/useful.h>
 
@@ -29,10 +32,11 @@
 
 struct grpc_grpclb_client_stats {
   gpr_refcount refs;
+  // This field must only be accessed via *_locked() methods.
+  grpc_grpclb_dropped_call_counts* drop_token_counts;
+  // These fields may be accessed from multiple threads at a time.
   gpr_atm num_calls_started;
   gpr_atm num_calls_finished;
-  gpr_atm num_calls_finished_with_drop_for_rate_limiting;
-  gpr_atm num_calls_finished_with_drop_for_load_balancing;
   gpr_atm num_calls_finished_with_client_failed_to_send;
   gpr_atm num_calls_finished_known_received;
 };
@@ -51,6 +55,7 @@
 
 void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats) {
   if (gpr_unref(&client_stats->refs)) {
+    grpc_grpclb_dropped_call_counts_destroy(client_stats->drop_token_counts);
     gpr_free(client_stats);
   }
 }
@@ -61,21 +66,9 @@
 }
 
 void grpc_grpclb_client_stats_add_call_finished(
-    bool finished_with_drop_for_rate_limiting,
-    bool finished_with_drop_for_load_balancing,
     bool finished_with_client_failed_to_send, bool finished_known_received,
     grpc_grpclb_client_stats* client_stats) {
   gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1);
-  if (finished_with_drop_for_rate_limiting) {
-    gpr_atm_full_fetch_add(
-        &client_stats->num_calls_finished_with_drop_for_rate_limiting,
-        (gpr_atm)1);
-  }
-  if (finished_with_drop_for_load_balancing) {
-    gpr_atm_full_fetch_add(
-        &client_stats->num_calls_finished_with_drop_for_load_balancing,
-        (gpr_atm)1);
-  }
   if (finished_with_client_failed_to_send) {
     gpr_atm_full_fetch_add(
         &client_stats->num_calls_finished_with_client_failed_to_send,
@@ -87,32 +80,70 @@
   }
 }
 
+void grpc_grpclb_client_stats_add_call_dropped_locked(
+    char* token, grpc_grpclb_client_stats* client_stats) {
+  // Increment num_calls_started and num_calls_finished.
+  gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1);
+  gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1);
+  // Record the drop.
+  if (client_stats->drop_token_counts == NULL) {
+    client_stats->drop_token_counts =
+        gpr_zalloc(sizeof(grpc_grpclb_dropped_call_counts));
+  }
+  grpc_grpclb_dropped_call_counts* drop_token_counts =
+      client_stats->drop_token_counts;
+  for (size_t i = 0; i < drop_token_counts->num_entries; ++i) {
+    if (strcmp(drop_token_counts->token_counts[i].token, token) == 0) {
+      ++drop_token_counts->token_counts[i].count;
+      return;
+    }
+  }
+  // Not found, so add a new entry.  We double the size of the array each time.
+  size_t new_num_entries = 2;
+  while (new_num_entries < drop_token_counts->num_entries + 1) {
+    new_num_entries *= 2;
+  }
+  drop_token_counts->token_counts =
+      gpr_realloc(drop_token_counts->token_counts,
+                  new_num_entries * sizeof(grpc_grpclb_drop_token_count));
+  grpc_grpclb_drop_token_count* new_entry =
+      &drop_token_counts->token_counts[drop_token_counts->num_entries++];
+  new_entry->token = gpr_strdup(token);
+  new_entry->count = 1;
+}
+
 static void atomic_get_and_reset_counter(int64_t* value, gpr_atm* counter) {
   *value = (int64_t)gpr_atm_acq_load(counter);
   gpr_atm_full_fetch_add(counter, (gpr_atm)(-*value));
 }
 
-void grpc_grpclb_client_stats_get(
+void grpc_grpclb_client_stats_get_locked(
     grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started,
     int64_t* num_calls_finished,
-    int64_t* num_calls_finished_with_drop_for_rate_limiting,
-    int64_t* num_calls_finished_with_drop_for_load_balancing,
     int64_t* num_calls_finished_with_client_failed_to_send,
-    int64_t* num_calls_finished_known_received) {
+    int64_t* num_calls_finished_known_received,
+    grpc_grpclb_dropped_call_counts** drop_token_counts) {
   atomic_get_and_reset_counter(num_calls_started,
                                &client_stats->num_calls_started);
   atomic_get_and_reset_counter(num_calls_finished,
                                &client_stats->num_calls_finished);
   atomic_get_and_reset_counter(
-      num_calls_finished_with_drop_for_rate_limiting,
-      &client_stats->num_calls_finished_with_drop_for_rate_limiting);
-  atomic_get_and_reset_counter(
-      num_calls_finished_with_drop_for_load_balancing,
-      &client_stats->num_calls_finished_with_drop_for_load_balancing);
-  atomic_get_and_reset_counter(
       num_calls_finished_with_client_failed_to_send,
       &client_stats->num_calls_finished_with_client_failed_to_send);
   atomic_get_and_reset_counter(
       num_calls_finished_known_received,
       &client_stats->num_calls_finished_known_received);
+  *drop_token_counts = client_stats->drop_token_counts;
+  client_stats->drop_token_counts = NULL;
+}
+
+void grpc_grpclb_dropped_call_counts_destroy(
+    grpc_grpclb_dropped_call_counts* drop_entries) {
+  if (drop_entries != NULL) {
+    for (size_t i = 0; i < drop_entries->num_entries; ++i) {
+      gpr_free(drop_entries->token_counts[i].token);
+    }
+    gpr_free(drop_entries->token_counts);
+    gpr_free(drop_entries);
+  }
 }
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
index 4bb47d5..c51e2a4 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
@@ -25,6 +25,16 @@
 
 typedef struct grpc_grpclb_client_stats grpc_grpclb_client_stats;
 
+typedef struct {
+  char* token;
+  int64_t count;
+} grpc_grpclb_drop_token_count;
+
+typedef struct {
+  grpc_grpclb_drop_token_count* token_counts;
+  size_t num_entries;
+} grpc_grpclb_dropped_call_counts;
+
 grpc_grpclb_client_stats* grpc_grpclb_client_stats_create();
 grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref(
     grpc_grpclb_client_stats* client_stats);
@@ -33,18 +43,23 @@
 void grpc_grpclb_client_stats_add_call_started(
     grpc_grpclb_client_stats* client_stats);
 void grpc_grpclb_client_stats_add_call_finished(
-    bool finished_with_drop_for_rate_limiting,
-    bool finished_with_drop_for_load_balancing,
     bool finished_with_client_failed_to_send, bool finished_known_received,
     grpc_grpclb_client_stats* client_stats);
 
-void grpc_grpclb_client_stats_get(
+// This method is not thread-safe; caller must synchronize.
+void grpc_grpclb_client_stats_add_call_dropped_locked(
+    char* token, grpc_grpclb_client_stats* client_stats);
+
+// This method is not thread-safe; caller must synchronize.
+void grpc_grpclb_client_stats_get_locked(
     grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started,
     int64_t* num_calls_finished,
-    int64_t* num_calls_finished_with_drop_for_rate_limiting,
-    int64_t* num_calls_finished_with_drop_for_load_balancing,
     int64_t* num_calls_finished_with_client_failed_to_send,
-    int64_t* num_calls_finished_known_received);
+    int64_t* num_calls_finished_known_received,
+    grpc_grpclb_dropped_call_counts** drop_token_counts);
+
+void grpc_grpclb_dropped_call_counts_destroy(
+    grpc_grpclb_dropped_call_counts* drop_entries);
 
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H \
           */
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
index bec7c97..6fa29f3 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
@@ -76,7 +76,33 @@
   timestamp_pb->nanos = timestamp.tv_nsec;
 }
 
-grpc_grpclb_request *grpc_grpclb_load_report_request_create(
+static bool encode_string(pb_ostream_t *stream, const pb_field_t *field,
+                          void *const *arg) {
+  char *str = *arg;
+  if (!pb_encode_tag_for_field(stream, field)) return false;
+  return pb_encode_string(stream, (uint8_t *)str, strlen(str));
+}
+
+static bool encode_drops(pb_ostream_t *stream, const pb_field_t *field,
+                         void *const *arg) {
+  grpc_grpclb_dropped_call_counts *drop_entries = *arg;
+  if (drop_entries == NULL) return true;
+  for (size_t i = 0; i < drop_entries->num_entries; ++i) {
+    if (!pb_encode_tag_for_field(stream, field)) return false;
+    grpc_lb_v1_ClientStatsPerToken drop_message;
+    drop_message.load_balance_token.funcs.encode = encode_string;
+    drop_message.load_balance_token.arg = drop_entries->token_counts[i].token;
+    drop_message.has_num_calls = true;
+    drop_message.num_calls = drop_entries->token_counts[i].count;
+    if (!pb_encode_submessage(stream, grpc_lb_v1_ClientStatsPerToken_fields,
+                              &drop_message)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+grpc_grpclb_request *grpc_grpclb_load_report_request_create_locked(
     grpc_grpclb_client_stats *client_stats) {
   grpc_grpclb_request *req = gpr_zalloc(sizeof(grpc_grpclb_request));
   req->has_client_stats = true;
@@ -84,18 +110,17 @@
   populate_timestamp(gpr_now(GPR_CLOCK_REALTIME), &req->client_stats.timestamp);
   req->client_stats.has_num_calls_started = true;
   req->client_stats.has_num_calls_finished = true;
-  req->client_stats.has_num_calls_finished_with_drop_for_rate_limiting = true;
-  req->client_stats.has_num_calls_finished_with_drop_for_load_balancing = true;
   req->client_stats.has_num_calls_finished_with_client_failed_to_send = true;
   req->client_stats.has_num_calls_finished_with_client_failed_to_send = true;
   req->client_stats.has_num_calls_finished_known_received = true;
-  grpc_grpclb_client_stats_get(
+  req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops;
+  grpc_grpclb_client_stats_get_locked(
       client_stats, &req->client_stats.num_calls_started,
       &req->client_stats.num_calls_finished,
-      &req->client_stats.num_calls_finished_with_drop_for_rate_limiting,
-      &req->client_stats.num_calls_finished_with_drop_for_load_balancing,
       &req->client_stats.num_calls_finished_with_client_failed_to_send,
-      &req->client_stats.num_calls_finished_known_received);
+      &req->client_stats.num_calls_finished_known_received,
+      (grpc_grpclb_dropped_call_counts **)&req->client_stats
+          .calls_finished_with_drop.arg);
   return req;
 }
 
@@ -117,6 +142,11 @@
 }
 
 void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
+  if (request->has_client_stats) {
+    grpc_grpclb_dropped_call_counts *drop_entries =
+        request->client_stats.calls_finished_with_drop.arg;
+    grpc_grpclb_dropped_call_counts_destroy(drop_entries);
+  }
   gpr_free(request);
 }
 
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
index ef8d563..c4a9849 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
@@ -44,7 +44,7 @@
 
 /** Create a request for a gRPC LB service under \a lb_service_name */
 grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name);
-grpc_grpclb_request *grpc_grpclb_load_report_request_create(
+grpc_grpclb_request *grpc_grpclb_load_report_request_create_locked(
     grpc_grpclb_client_stats *client_stats);
 
 /** Protocol Buffers v3-encode \a request */
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
index fb119c7..6a5d54c 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
@@ -33,14 +33,19 @@
     PB_LAST_FIELD
 };
 
-const pb_field_t grpc_lb_v1_ClientStats_fields[8] = {
+const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, grpc_lb_v1_ClientStatsPerToken, load_balance_token, load_balance_token, 0),
+    PB_FIELD(  2, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStatsPerToken, num_calls, load_balance_token, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v1_ClientStats_fields[7] = {
     PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v1_ClientStats, timestamp, timestamp, &grpc_lb_v1_Timestamp_fields),
     PB_FIELD(  2, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_started, timestamp, 0),
     PB_FIELD(  3, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished, num_calls_started, 0),
-    PB_FIELD(  4, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_drop_for_rate_limiting, num_calls_finished, 0),
-    PB_FIELD(  5, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_drop_for_load_balancing, num_calls_finished_with_drop_for_rate_limiting, 0),
-    PB_FIELD(  6, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_client_failed_to_send, num_calls_finished_with_drop_for_load_balancing, 0),
+    PB_FIELD(  6, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_client_failed_to_send, num_calls_finished, 0),
     PB_FIELD(  7, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_known_received, num_calls_finished_with_client_failed_to_send, 0),
+    PB_FIELD(  8, MESSAGE , REPEATED, CALLBACK, OTHER, grpc_lb_v1_ClientStats, calls_finished_with_drop, num_calls_finished_known_received, &grpc_lb_v1_ClientStatsPerToken_fields),
     PB_LAST_FIELD
 };
 
@@ -62,12 +67,11 @@
     PB_LAST_FIELD
 };
 
-const pb_field_t grpc_lb_v1_Server_fields[6] = {
+const pb_field_t grpc_lb_v1_Server_fields[5] = {
     PB_FIELD(  1, BYTES   , OPTIONAL, STATIC  , FIRST, grpc_lb_v1_Server, ip_address, ip_address, 0),
     PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_Server, port, ip_address, 0),
     PB_FIELD(  3, STRING  , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_Server, load_balance_token, port, 0),
-    PB_FIELD(  4, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_Server, drop_for_rate_limiting, load_balance_token, 0),
-    PB_FIELD(  5, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_Server, drop_for_load_balancing, drop_for_rate_limiting, 0),
+    PB_FIELD(  4, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v1_Server, drop, load_balance_token, 0),
     PB_LAST_FIELD
 };
 
@@ -81,7 +85,7 @@
  * numbers or field sizes that are larger than what can fit in 8 or 16 bit
  * field descriptors.
  */
-PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
 #endif
 
 #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@@ -92,7 +96,7 @@
  * numbers or field sizes that are larger than what can fit in the default
  * 8 bit descriptors.
  */
-PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
 #endif
 
 
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
index d3ae919..93333d1 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
@@ -14,6 +14,13 @@
 #endif
 
 /* Struct definitions */
+typedef struct _grpc_lb_v1_ClientStatsPerToken {
+    pb_callback_t load_balance_token;
+    bool has_num_calls;
+    int64_t num_calls;
+/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStatsPerToken) */
+} grpc_lb_v1_ClientStatsPerToken;
+
 typedef struct _grpc_lb_v1_Duration {
     bool has_seconds;
     int64_t seconds;
@@ -36,10 +43,8 @@
     int32_t port;
     bool has_load_balance_token;
     char load_balance_token[50];
-    bool has_drop_for_rate_limiting;
-    bool drop_for_rate_limiting;
-    bool has_drop_for_load_balancing;
-    bool drop_for_load_balancing;
+    bool has_drop;
+    bool drop;
 /* @@protoc_insertion_point(struct:grpc_lb_v1_Server) */
 } grpc_lb_v1_Server;
 
@@ -58,14 +63,11 @@
     int64_t num_calls_started;
     bool has_num_calls_finished;
     int64_t num_calls_finished;
-    bool has_num_calls_finished_with_drop_for_rate_limiting;
-    int64_t num_calls_finished_with_drop_for_rate_limiting;
-    bool has_num_calls_finished_with_drop_for_load_balancing;
-    int64_t num_calls_finished_with_drop_for_load_balancing;
     bool has_num_calls_finished_with_client_failed_to_send;
     int64_t num_calls_finished_with_client_failed_to_send;
     bool has_num_calls_finished_known_received;
     int64_t num_calls_finished_known_received;
+    pb_callback_t calls_finished_with_drop;
 /* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */
 } grpc_lb_v1_ClientStats;
 
@@ -107,39 +109,41 @@
 #define grpc_lb_v1_Timestamp_init_default        {false, 0, false, 0}
 #define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default}
 #define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""}
-#define grpc_lb_v1_ClientStats_init_default      {false, grpc_lb_v1_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
+#define grpc_lb_v1_ClientStatsPerToken_init_default {{{NULL}, NULL}, false, 0}
+#define grpc_lb_v1_ClientStats_init_default      {false, grpc_lb_v1_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
 #define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default}
 #define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default}
 #define grpc_lb_v1_ServerList_init_default       {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_default}
-#define grpc_lb_v1_Server_init_default           {false, {0, {0}}, false, 0, false, "", false, 0, false, 0}
+#define grpc_lb_v1_Server_init_default           {false, {0, {0}}, false, 0, false, "", false, 0}
 #define grpc_lb_v1_Duration_init_zero            {false, 0, false, 0}
 #define grpc_lb_v1_Timestamp_init_zero           {false, 0, false, 0}
 #define grpc_lb_v1_LoadBalanceRequest_init_zero  {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero}
 #define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""}
-#define grpc_lb_v1_ClientStats_init_zero         {false, grpc_lb_v1_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
+#define grpc_lb_v1_ClientStatsPerToken_init_zero {{{NULL}, NULL}, false, 0}
+#define grpc_lb_v1_ClientStats_init_zero         {false, grpc_lb_v1_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
 #define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero}
 #define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero}
 #define grpc_lb_v1_ServerList_init_zero          {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_zero}
-#define grpc_lb_v1_Server_init_zero              {false, {0, {0}}, false, 0, false, "", false, 0, false, 0}
+#define grpc_lb_v1_Server_init_zero              {false, {0, {0}}, false, 0, false, "", false, 0}
 
 /* Field tags (for use in manual encoding/decoding) */
+#define grpc_lb_v1_ClientStatsPerToken_load_balance_token_tag 1
+#define grpc_lb_v1_ClientStatsPerToken_num_calls_tag 2
 #define grpc_lb_v1_Duration_seconds_tag          1
 #define grpc_lb_v1_Duration_nanos_tag            2
 #define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1
 #define grpc_lb_v1_Server_ip_address_tag         1
 #define grpc_lb_v1_Server_port_tag               2
 #define grpc_lb_v1_Server_load_balance_token_tag 3
-#define grpc_lb_v1_Server_drop_for_rate_limiting_tag 4
-#define grpc_lb_v1_Server_drop_for_load_balancing_tag 5
+#define grpc_lb_v1_Server_drop_tag               4
 #define grpc_lb_v1_Timestamp_seconds_tag         1
 #define grpc_lb_v1_Timestamp_nanos_tag           2
 #define grpc_lb_v1_ClientStats_timestamp_tag     1
 #define grpc_lb_v1_ClientStats_num_calls_started_tag 2
 #define grpc_lb_v1_ClientStats_num_calls_finished_tag 3
-#define grpc_lb_v1_ClientStats_num_calls_finished_with_drop_for_rate_limiting_tag 4
-#define grpc_lb_v1_ClientStats_num_calls_finished_with_drop_for_load_balancing_tag 5
 #define grpc_lb_v1_ClientStats_num_calls_finished_with_client_failed_to_send_tag 6
 #define grpc_lb_v1_ClientStats_num_calls_finished_known_received_tag 7
+#define grpc_lb_v1_ClientStats_calls_finished_with_drop_tag 8
 #define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 1
 #define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 2
 #define grpc_lb_v1_ServerList_servers_tag        1
@@ -154,22 +158,24 @@
 extern const pb_field_t grpc_lb_v1_Timestamp_fields[3];
 extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3];
 extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2];
-extern const pb_field_t grpc_lb_v1_ClientStats_fields[8];
+extern const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3];
+extern const pb_field_t grpc_lb_v1_ClientStats_fields[7];
 extern const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3];
 extern const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3];
 extern const pb_field_t grpc_lb_v1_ServerList_fields[3];
-extern const pb_field_t grpc_lb_v1_Server_fields[6];
+extern const pb_field_t grpc_lb_v1_Server_fields[5];
 
 /* Maximum encoded size of messages (where known) */
 #define grpc_lb_v1_Duration_size                 22
 #define grpc_lb_v1_Timestamp_size                22
-#define grpc_lb_v1_LoadBalanceRequest_size       226
+#define grpc_lb_v1_LoadBalanceRequest_size       (140 + grpc_lb_v1_ClientStats_size)
 #define grpc_lb_v1_InitialLoadBalanceRequest_size 131
-#define grpc_lb_v1_ClientStats_size              90
+/* grpc_lb_v1_ClientStatsPerToken_size depends on runtime parameters */
+/* grpc_lb_v1_ClientStats_size depends on runtime parameters */
 #define grpc_lb_v1_LoadBalanceResponse_size      (98 + grpc_lb_v1_ServerList_size)
 #define grpc_lb_v1_InitialLoadBalanceResponse_size 90
 /* grpc_lb_v1_ServerList_size depends on runtime parameters */
-#define grpc_lb_v1_Server_size                   85
+#define grpc_lb_v1_Server_size                   83
 
 /* Message IDs (where set with "msgid" option) */
 #ifdef PB_MSGID
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
index d0acd7a..fd0fb41 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
@@ -28,7 +28,8 @@
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
-grpc_tracer_flag grpc_lb_pick_first_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_lb_pick_first_trace =
+    GRPC_TRACER_INITIALIZER(false, "pick_first");
 
 typedef struct pending_pick {
   struct pending_pick *next;
@@ -707,7 +708,7 @@
 
 void grpc_lb_policy_pick_first_init() {
   grpc_register_lb_policy(pick_first_lb_factory_create());
-  grpc_register_tracer("pick_first", &grpc_lb_pick_first_trace);
+  grpc_register_tracer(&grpc_lb_pick_first_trace);
 }
 
 void grpc_lb_policy_pick_first_shutdown() {}
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
index fbef79e..a7f7e95 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
@@ -37,7 +37,8 @@
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/static_metadata.h"
 
-grpc_tracer_flag grpc_lb_round_robin_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_lb_round_robin_trace =
+    GRPC_TRACER_INITIALIZER(false, "round_robin");
 
 /** List of entities waiting for a pick.
  *
@@ -73,6 +74,9 @@
   bool started_picking;
   /** are we shutting down? */
   bool shutdown;
+  /** has the policy gotten into the GRPC_CHANNEL_SHUTDOWN? No picks can be
+   * service after this point, the policy will never transition out. */
+  bool in_connectivity_shutdown;
   /** List of picks that are waiting on connectivity */
   pending_pick *pending_picks;
 
@@ -141,6 +145,21 @@
   bool shutting_down;
 };
 
+static rr_subchannel_list *rr_subchannel_list_create(round_robin_lb_policy *p,
+                                                     size_t num_subchannels) {
+  rr_subchannel_list *subchannel_list = gpr_zalloc(sizeof(*subchannel_list));
+  subchannel_list->policy = p;
+  subchannel_list->subchannels =
+      gpr_zalloc(sizeof(subchannel_data) * num_subchannels);
+  subchannel_list->num_subchannels = num_subchannels;
+  gpr_ref_init(&subchannel_list->refcount, 1);
+  if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
+    gpr_log(GPR_INFO, "[RR %p] Created subchannel list %p for %lu subchannels",
+            (void *)p, (void *)subchannel_list, (unsigned long)num_subchannels);
+  }
+  return subchannel_list;
+}
+
 static void rr_subchannel_list_destroy(grpc_exec_ctx *exec_ctx,
                                        rr_subchannel_list *subchannel_list) {
   GPR_ASSERT(subchannel_list->shutting_down);
@@ -170,9 +189,9 @@
   gpr_ref_non_zero(&subchannel_list->refcount);
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
-    gpr_log(GPR_INFO, "[RR %p] subchannel_list %p REF %lu->%lu",
+    gpr_log(GPR_INFO, "[RR %p] subchannel_list %p REF %lu->%lu (%s)",
             (void *)subchannel_list->policy, (void *)subchannel_list,
-            (unsigned long)(count - 1), (unsigned long)count);
+            (unsigned long)(count - 1), (unsigned long)count, reason);
   }
 }
 
@@ -182,9 +201,9 @@
   const bool done = gpr_unref(&subchannel_list->refcount);
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
-    gpr_log(GPR_INFO, "[RR %p] subchannel_list %p UNREF %lu->%lu",
+    gpr_log(GPR_INFO, "[RR %p] subchannel_list %p UNREF %lu->%lu (%s)",
             (void *)subchannel_list->policy, (void *)subchannel_list,
-            (unsigned long)(count + 1), (unsigned long)count);
+            (unsigned long)(count + 1), (unsigned long)count, reason);
   }
   if (done) {
     rr_subchannel_list_destroy(exec_ctx, subchannel_list);
@@ -193,19 +212,13 @@
 
 /** Mark \a subchannel_list as discarded. Unsubscribes all its subchannels. The
  * watcher's callback will ultimately unref \a subchannel_list.  */
-static void rr_subchannel_list_shutdown(grpc_exec_ctx *exec_ctx,
-                                        rr_subchannel_list *subchannel_list,
-                                        const char *reason) {
-  if (subchannel_list->shutting_down) {
-    if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-      gpr_log(GPR_DEBUG, "Subchannel list %p already shutting down",
-              (void *)subchannel_list);
-    }
-    return;
-  };
+static void rr_subchannel_list_shutdown_and_unref(
+    grpc_exec_ctx *exec_ctx, rr_subchannel_list *subchannel_list,
+    const char *reason) {
+  GPR_ASSERT(!subchannel_list->shutting_down);
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_DEBUG, "Shutting down subchannel_list %p",
-            (void *)subchannel_list);
+    gpr_log(GPR_DEBUG, "[RR %p] Shutting down subchannel_list %p (%s)",
+            (void *)subchannel_list->policy, (void *)subchannel_list, reason);
   }
   GPR_ASSERT(!subchannel_list->shutting_down);
   subchannel_list->shutting_down = true;
@@ -213,10 +226,12 @@
     subchannel_data *sd = &subchannel_list->subchannels[i];
     if (sd->subchannel != NULL) {  // if subchannel isn't shutdown, unsubscribe.
       if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-        gpr_log(GPR_DEBUG,
-                "Unsubscribing from subchannel %p as part of shutting down "
-                "subchannel_list %p",
-                (void *)sd->subchannel, (void *)subchannel_list);
+        gpr_log(
+            GPR_DEBUG,
+            "[RR %p] Unsubscribing from subchannel %p as part of shutting down "
+            "subchannel_list %p",
+            (void *)subchannel_list->policy, (void *)sd->subchannel,
+            (void *)subchannel_list);
       }
       grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL,
                                              NULL,
@@ -293,7 +308,8 @@
 static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol);
+    gpr_log(GPR_DEBUG, "[RR %p] Destroying Round Robin policy at %p",
+            (void *)pol, (void *)pol);
   }
   grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
   gpr_free(p);
@@ -302,7 +318,8 @@
 static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol);
+    gpr_log(GPR_DEBUG, "[RR %p] Shutting down Round Robin policy at %p",
+            (void *)pol, (void *)pol);
   }
   p->shutdown = true;
   pending_pick *pp;
@@ -317,9 +334,18 @@
   grpc_connectivity_state_set(
       exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "rr_shutdown");
-  rr_subchannel_list_shutdown(exec_ctx, p->subchannel_list,
-                              "sl_shutdown_rr_shutdown");
+  const bool latest_is_current =
+      p->subchannel_list == p->latest_pending_subchannel_list;
+  rr_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list,
+                                        "sl_shutdown_rr_shutdown");
   p->subchannel_list = NULL;
+  if (!latest_is_current && p->latest_pending_subchannel_list != NULL &&
+      !p->latest_pending_subchannel_list->shutting_down) {
+    rr_subchannel_list_shutdown_and_unref(exec_ctx,
+                                          p->latest_pending_subchannel_list,
+                                          "sl_shutdown_pending_rr_shutdown");
+    p->latest_pending_subchannel_list = NULL;
+  }
 }
 
 static void rr_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
@@ -375,8 +401,8 @@
   p->started_picking = true;
   for (size_t i = 0; i < p->subchannel_list->num_subchannels; i++) {
     subchannel_data *sd = &p->subchannel_list->subchannels[i];
-    GRPC_LB_POLICY_WEAK_REF(&p->base, "rr_connectivity");
-    rr_subchannel_list_ref(sd->subchannel_list, "start_picking");
+    GRPC_LB_POLICY_WEAK_REF(&p->base, "start_picking_locked");
+    rr_subchannel_list_ref(sd->subchannel_list, "started_picking");
     grpc_subchannel_notify_on_state_change(
         exec_ctx, sd->subchannel, p->base.interested_parties,
         &sd->pending_connectivity_state_unsafe,
@@ -397,8 +423,10 @@
                           grpc_call_context_element *context, void **user_data,
                           grpc_closure *on_complete) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  GPR_ASSERT(!p->shutdown);
+  GPR_ASSERT(!p->in_connectivity_shutdown);
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol);
+    gpr_log(GPR_INFO, "[RR %p] Trying to pick", (void *)pol);
   }
   if (p->subchannel_list != NULL) {
     const size_t next_ready_index = get_next_ready_subchannel_index_locked(p);
@@ -414,8 +442,8 @@
       if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
         gpr_log(
             GPR_DEBUG,
-            "[RR %p] PICKED TARGET <-- SUBCHANNEL %p (CONNECTED %p) (SL %p, "
-            "INDEX %lu)",
+            "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
+            "index %lu)",
             (void *)p, (void *)sd->subchannel, (void *)*target,
             (void *)sd->subchannel_list, (unsigned long)next_ready_index);
       }
@@ -509,6 +537,7 @@
     grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
                                 GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error),
                                 "rr_shutdown");
+    p->in_connectivity_shutdown = true;
     new_state = GRPC_CHANNEL_SHUTDOWN;
   } else if (subchannel_list->num_transient_failures ==
              p->subchannel_list->num_subchannels) { /* 4) TRANSIENT_FAILURE */
@@ -544,22 +573,33 @@
   }
   // If the policy is shutting down, unref and return.
   if (p->shutdown) {
-    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, "pol_shutdown");
+    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list,
+                             "pol_shutdown+started_picking");
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pol_shutdown");
     return;
   }
   if (sd->subchannel_list->shutting_down && error == GRPC_ERROR_CANCELLED) {
     // the subchannel list associated with sd has been discarded. This callback
-    // corresponds to the unsubscription.
-    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, "sl_shutdown");
-    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "sl_shutdown");
+    // corresponds to the unsubscription. The unrefs correspond to the picking
+    // ref (start_picking_locked or update_started_picking).
+    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list,
+                             "sl_shutdown+started_picking");
+    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "sl_shutdown+picking");
     return;
   }
   // Dispose of outdated subchannel lists.
   if (sd->subchannel_list != p->subchannel_list &&
       sd->subchannel_list != p->latest_pending_subchannel_list) {
-    // sd belongs to an outdated subchannel_list: get rid of it.
-    rr_subchannel_list_shutdown(exec_ctx, sd->subchannel_list, "sl_oudated");
+    char *reason = NULL;
+    if (sd->subchannel_list->shutting_down) {
+      reason = "sl_outdated_straggler";
+      rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, reason);
+    } else {
+      reason = "sl_outdated";
+      rr_subchannel_list_shutdown_and_unref(exec_ctx, sd->subchannel_list,
+                                            reason);
+    }
+    GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, reason);
     return;
   }
   // Now that we're inside the combiner, copy the pending connectivity
@@ -582,7 +622,7 @@
       sd->user_data = NULL;
     }
     if (new_policy_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
-      /* the policy is shutting down. Flush all the pending picks... */
+      // the policy is shutting down. Flush all the pending picks...
       pending_pick *pp;
       while ((pp = p->pending_picks)) {
         p->pending_picks = pp->next;
@@ -591,8 +631,9 @@
         gpr_free(pp);
       }
     }
-    /* unref the "rr_connectivity" weak ref from start_picking */
-    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, "sd_shutdown");
+    rr_subchannel_list_unref(exec_ctx, sd->subchannel_list,
+                             "sd_shutdown+started_picking");
+    // unref the "rr_connectivity_update" weak ref from start_picking.
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
                               "rr_connectivity_sd_shutdown");
   } else {  // sd not in SHUTDOWN
@@ -617,10 +658,10 @@
         }
         if (p->subchannel_list != NULL) {
           // dispose of the current subchannel_list
-          rr_subchannel_list_shutdown(exec_ctx, p->subchannel_list,
-                                      "sl_shutdown_rr_update_connectivity");
+          rr_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list,
+                                                "sl_phase_out_shutdown");
         }
-        p->subchannel_list = sd->subchannel_list;
+        p->subchannel_list = p->latest_pending_subchannel_list;
         p->latest_pending_subchannel_list = NULL;
       }
       /* at this point we know there's at least one suitable subchannel. Go
@@ -631,8 +672,8 @@
       subchannel_data *selected =
           &p->subchannel_list->subchannels[next_ready_index];
       if (p->pending_picks != NULL) {
-        /* if the selected subchannel is going to be used for the pending
-         * picks, update the last picked pointer */
+        // if the selected subchannel is going to be used for the pending
+        // picks, update the last picked pointer
         update_last_ready_subchannel_index_locked(p, next_ready_index);
       }
       pending_pick *pp;
@@ -646,16 +687,17 @@
         }
         if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
           gpr_log(GPR_DEBUG,
-                  "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (INDEX %lu)",
-                  (void *)selected->subchannel,
-                  (unsigned long)next_ready_index);
+                  "[RR %p] Fulfilling pending pick. Target <-- subchannel %p "
+                  "(subchannel_list %p, index %lu)",
+                  (void *)p, (void *)selected->subchannel,
+                  (void *)p->subchannel_list, (unsigned long)next_ready_index);
         }
         GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
         gpr_free(pp);
       }
     }
-    /* renew notification: reuses the "rr_connectivity" weak ref on the policy
-     * as well as the sd->subchannel_list ref. */
+    /* renew notification: reuses the "rr_connectivity_update" weak ref on the
+     * policy as well as the sd->subchannel_list ref. */
     grpc_subchannel_notify_on_state_change(
         exec_ctx, sd->subchannel, p->base.interested_parties,
         &sd->pending_connectivity_state_unsafe,
@@ -713,8 +755,7 @@
     } else {
       // otherwise, keep using the current subchannel list (ignore this update).
       gpr_log(GPR_ERROR,
-              "No valid LB addresses channel arg for Round Robin %p update, "
-              "ignoring.",
+              "[RR %p] No valid LB addresses channel arg for update, ignoring.",
               (void *)p);
     }
     return;
@@ -724,30 +765,32 @@
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     if (!addresses->addresses[i].is_balancer) ++num_addrs;
   }
+  rr_subchannel_list *subchannel_list = rr_subchannel_list_create(p, num_addrs);
   if (num_addrs == 0) {
     grpc_connectivity_state_set(
         exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
         "rr_update_empty");
     if (p->subchannel_list != NULL) {
-      rr_subchannel_list_shutdown(exec_ctx, p->subchannel_list,
-                                  "sl_shutdown_rr_update");
-      p->subchannel_list = NULL;
+      rr_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list,
+                                            "sl_shutdown_empty_update");
     }
+    p->subchannel_list = subchannel_list;  // empty list
     return;
   }
   size_t subchannel_index = 0;
-  rr_subchannel_list *subchannel_list = gpr_zalloc(sizeof(*subchannel_list));
-  subchannel_list->policy = p;
-  subchannel_list->subchannels =
-      gpr_zalloc(sizeof(subchannel_data) * num_addrs);
-  subchannel_list->num_subchannels = num_addrs;
-  gpr_ref_init(&subchannel_list->refcount, 1);
-  p->latest_pending_subchannel_list = subchannel_list;
-  if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_DEBUG, "Created subchannel list %p for %lu subchannels",
-            (void *)subchannel_list, (unsigned long)num_addrs);
+  if (p->latest_pending_subchannel_list != NULL && p->started_picking) {
+    if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
+      gpr_log(GPR_DEBUG,
+              "[RR %p] Shutting down latest pending subchannel list %p, about "
+              "to be replaced by newer latest %p",
+              (void *)p, (void *)p->latest_pending_subchannel_list,
+              (void *)subchannel_list);
+    }
+    rr_subchannel_list_shutdown_and_unref(
+        exec_ctx, p->latest_pending_subchannel_list, "sl_outdated_dont_smash");
   }
+  p->latest_pending_subchannel_list = subchannel_list;
   grpc_subchannel_args sc_args;
   /* 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. */
@@ -771,11 +814,12 @@
     if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
       char *address_uri =
           grpc_sockaddr_to_uri(&addresses->addresses[i].address);
-      gpr_log(GPR_DEBUG,
-              "index %lu: Created subchannel %p for address uri %s into "
-              "subchannel_list %p",
-              (unsigned long)subchannel_index, (void *)subchannel, address_uri,
-              (void *)subchannel_list);
+      gpr_log(
+          GPR_DEBUG,
+          "[RR %p] index %lu: Created subchannel %p for address uri %s into "
+          "subchannel_list %p",
+          (void *)p, (unsigned long)subchannel_index, (void *)subchannel,
+          address_uri, (void *)subchannel_list);
       gpr_free(address_uri);
     }
     grpc_channel_args_destroy(exec_ctx, new_args);
@@ -814,10 +858,11 @@
     // The policy isn't picking yet. Save the update for later, disposing of
     // previous version if any.
     if (p->subchannel_list != NULL) {
-      rr_subchannel_list_shutdown(exec_ctx, p->subchannel_list,
-                                  "rr_update_before_started_picking");
+      rr_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list,
+                                            "rr_update_before_started_picking");
     }
     p->subchannel_list = subchannel_list;
+    p->latest_pending_subchannel_list = NULL;
   }
 }
 
@@ -842,12 +887,12 @@
                                           grpc_lb_policy_args *args) {
   GPR_ASSERT(args->client_channel_factory != NULL);
   round_robin_lb_policy *p = gpr_zalloc(sizeof(*p));
-  rr_update_locked(exec_ctx, &p->base, args);
   grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
   grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
                                "round_robin");
+  rr_update_locked(exec_ctx, &p->base, args);
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
-    gpr_log(GPR_DEBUG, "Created Round Robin %p with %lu subchannels", (void *)p,
+    gpr_log(GPR_DEBUG, "[RR %p] Created with %lu subchannels", (void *)p,
             (unsigned long)p->subchannel_list->num_subchannels);
   }
   return &p->base;
@@ -868,7 +913,7 @@
 
 void grpc_lb_policy_round_robin_init() {
   grpc_register_lb_policy(round_robin_lb_factory_create());
-  grpc_register_tracer("round_robin", &grpc_lb_round_robin_trace);
+  grpc_register_tracer(&grpc_lb_round_robin_trace);
 }
 
 void grpc_lb_policy_round_robin_shutdown() {}
diff --git a/src/core/ext/filters/client_channel/resolver.c b/src/core/ext/filters/client_channel/resolver.c
index de9a8ce..8401504 100644
--- a/src/core/ext/filters/client_channel/resolver.c
+++ b/src/core/ext/filters/client_channel/resolver.c
@@ -20,7 +20,8 @@
 #include "src/core/lib/iomgr/combiner.h"
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_resolver_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_resolver_refcount =
+    GRPC_TRACER_INITIALIZER(false, "resolver_refcount");
 #endif
 
 void grpc_resolver_init(grpc_resolver *resolver,
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
index 1ab8295..b696344 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
@@ -103,10 +103,9 @@
   grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd);
   /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up
      immediately by another thread, and should not be closed by the following
-     grpc_fd_orphan. To prevent this fd from being closed by grpc_fd_orphan,
-     a fd pointer is provided. */
-  int fd;
-  grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, &fd, "c-ares query finished");
+     grpc_fd_orphan. */
+  grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, true /* already_closed */,
+                 "c-ares query finished");
   gpr_free(fdn);
 }
 
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
index 244b260..6ec3790 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
@@ -33,13 +33,13 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include <nameser.h>
 
 #include "src/core/ext/filters/client_channel/parse_address.h"
 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
+#include "src/core/lib/iomgr/nameser.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/support/string.h"
 
@@ -236,12 +236,12 @@
            srv_it = srv_it->next) {
         if (grpc_ipv6_loopback_available()) {
           grpc_ares_hostbyname_request *hr = create_hostbyname_request(
-              r, srv_it->host, srv_it->port, true /* is_balancer */);
+              r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
           ares_gethostbyname(*channel, hr->host, AF_INET6,
                              on_hostbyname_done_cb, hr);
         }
         grpc_ares_hostbyname_request *hr = create_hostbyname_request(
-            r, srv_it->host, srv_it->port, true /* is_balancer */);
+            r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
         ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb,
                            hr);
         grpc_ares_ev_driver_start(&exec_ctx, r->ev_driver);
diff --git a/src/core/ext/filters/client_channel/retry_throttle.c b/src/core/ext/filters/client_channel/retry_throttle.c
index 3009e21..0c7a3ae 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.c
+++ b/src/core/ext/filters/client_channel/retry_throttle.c
@@ -130,24 +130,28 @@
 // avl vtable for string -> server_retry_throttle_data map
 //
 
-static void* copy_server_name(void* key) { return gpr_strdup(key); }
+static void* copy_server_name(void* key, void* unused) {
+  return gpr_strdup(key);
+}
 
-static long compare_server_name(void* key1, void* key2) {
+static long compare_server_name(void* key1, void* key2, void* unused) {
   return strcmp(key1, key2);
 }
 
-static void destroy_server_retry_throttle_data(void* value) {
+static void destroy_server_retry_throttle_data(void* value, void* unused) {
   grpc_server_retry_throttle_data* throttle_data = value;
   grpc_server_retry_throttle_data_unref(throttle_data);
 }
 
-static void* copy_server_retry_throttle_data(void* value) {
+static void* copy_server_retry_throttle_data(void* value, void* unused) {
   grpc_server_retry_throttle_data* throttle_data = value;
   return grpc_server_retry_throttle_data_ref(throttle_data);
 }
 
+static void destroy_server_name(void* key, void* unused) { gpr_free(key); }
+
 static const gpr_avl_vtable avl_vtable = {
-    gpr_free /* destroy_key */, copy_server_name, compare_server_name,
+    destroy_server_name, copy_server_name, compare_server_name,
     destroy_server_retry_throttle_data, copy_server_retry_throttle_data};
 
 //
@@ -164,19 +168,19 @@
 
 void grpc_retry_throttle_map_shutdown() {
   gpr_mu_destroy(&g_mu);
-  gpr_avl_unref(g_avl);
+  gpr_avl_unref(g_avl, NULL);
 }
 
 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) {
   gpr_mu_lock(&g_mu);
   grpc_server_retry_throttle_data* throttle_data =
-      gpr_avl_get(g_avl, (char*)server_name);
+      gpr_avl_get(g_avl, (char*)server_name, NULL);
   if (throttle_data == NULL) {
     // Entry not found.  Create a new one.
     throttle_data = grpc_server_retry_throttle_data_create(
         max_milli_tokens, milli_token_ratio, NULL);
-    g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data);
+    g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data, NULL);
   } else {
     if (throttle_data->max_milli_tokens != max_milli_tokens ||
         throttle_data->milli_token_ratio != milli_token_ratio) {
@@ -184,7 +188,7 @@
       // the original one.
       throttle_data = grpc_server_retry_throttle_data_create(
           max_milli_tokens, milli_token_ratio, throttle_data);
-      g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data);
+      g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data, NULL);
     } else {
       // Entry found.  Increase refcount.
       grpc_server_retry_throttle_data_ref(throttle_data);
diff --git a/src/core/ext/filters/client_channel/subchannel.c b/src/core/ext/filters/client_channel/subchannel.c
index 88157ed..5788819 100644
--- a/src/core/ext/filters/client_channel/subchannel.c
+++ b/src/core/ext/filters/client_channel/subchannel.c
@@ -188,6 +188,7 @@
   grpc_connector_unref(exec_ctx, c->connector);
   grpc_pollset_set_destroy(exec_ctx, c->pollset_set);
   grpc_subchannel_key_destroy(exec_ctx, c->key);
+  gpr_mu_destroy(&c->mu);
   gpr_free(c);
 }
 
diff --git a/src/core/ext/filters/client_channel/subchannel_index.c b/src/core/ext/filters/client_channel/subchannel_index.c
index e291ca9..ababd05 100644
--- a/src/core/ext/filters/client_channel/subchannel_index.c
+++ b/src/core/ext/filters/client_channel/subchannel_index.c
@@ -38,23 +38,7 @@
   grpc_subchannel_args args;
 };
 
-GPR_TLS_DECL(subchannel_index_exec_ctx);
-
-static void enter_ctx(grpc_exec_ctx *exec_ctx) {
-  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0);
-  gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx);
-}
-
-static void leave_ctx(grpc_exec_ctx *exec_ctx) {
-  GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx);
-  gpr_tls_set(&subchannel_index_exec_ctx, 0);
-}
-
-static grpc_exec_ctx *current_ctx() {
-  grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx);
-  GPR_ASSERT(c != NULL);
-  return c;
-}
+static bool g_force_creation = false;
 
 static grpc_subchannel_key *create_key(
     const grpc_subchannel_args *args,
@@ -84,6 +68,7 @@
 
 int grpc_subchannel_key_compare(const grpc_subchannel_key *a,
                                 const grpc_subchannel_key *b) {
+  if (g_force_creation) return false;
   int c = GPR_ICMP(a->args.filter_count, b->args.filter_count);
   if (c != 0) return c;
   if (a->args.filter_count > 0) {
@@ -101,21 +86,25 @@
   gpr_free(k);
 }
 
-static void sck_avl_destroy(void *p) {
-  grpc_subchannel_key_destroy(current_ctx(), p);
+static void sck_avl_destroy(void *p, void *user_data) {
+  grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data;
+  grpc_subchannel_key_destroy(exec_ctx, p);
 }
 
-static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); }
+static void *sck_avl_copy(void *p, void *unused) {
+  return subchannel_key_copy(p);
+}
 
-static long sck_avl_compare(void *a, void *b) {
+static long sck_avl_compare(void *a, void *b, void *unused) {
   return grpc_subchannel_key_compare(a, b);
 }
 
-static void scv_avl_destroy(void *p) {
-  GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index");
+static void scv_avl_destroy(void *p, void *user_data) {
+  grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data;
+  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, p, "subchannel_index");
 }
 
-static void *scv_avl_copy(void *p) {
+static void *scv_avl_copy(void *p, void *unused) {
   GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index");
   return p;
 }
@@ -130,38 +119,33 @@
 void grpc_subchannel_index_init(void) {
   g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
   gpr_mu_init(&g_mu);
-  gpr_tls_init(&subchannel_index_exec_ctx);
 }
 
 void grpc_subchannel_index_shutdown(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   gpr_mu_destroy(&g_mu);
-  gpr_avl_unref(g_subchannel_index);
-  gpr_tls_destroy(&subchannel_index_exec_ctx);
+  gpr_avl_unref(g_subchannel_index, &exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
                                             grpc_subchannel_key *key) {
-  enter_ctx(exec_ctx);
-
   // Lock, and take a reference to the subchannel index.
   // We don't need to do the search under a lock as avl's are immutable.
   gpr_mu_lock(&g_mu);
-  gpr_avl index = gpr_avl_ref(g_subchannel_index);
+  gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx);
   gpr_mu_unlock(&g_mu);
 
-  grpc_subchannel *c =
-      GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find");
-  gpr_avl_unref(index);
+  grpc_subchannel *c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(
+      gpr_avl_get(index, key, exec_ctx), "index_find");
+  gpr_avl_unref(index, exec_ctx);
 
-  leave_ctx(exec_ctx);
   return c;
 }
 
 grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
                                                 grpc_subchannel_key *key,
                                                 grpc_subchannel *constructed) {
-  enter_ctx(exec_ctx);
-
   grpc_subchannel *c = NULL;
   bool need_to_unref_constructed;
 
@@ -171,11 +155,11 @@
     // Compare and swap loop:
     // - take a reference to the current index
     gpr_mu_lock(&g_mu);
-    gpr_avl index = gpr_avl_ref(g_subchannel_index);
+    gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx);
     gpr_mu_unlock(&g_mu);
 
     // - Check to see if a subchannel already exists
-    c = gpr_avl_get(index, key);
+    c = gpr_avl_get(index, key, exec_ctx);
     if (c != NULL) {
       c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "index_register");
     }
@@ -184,9 +168,9 @@
       need_to_unref_constructed = true;
     } else {
       // no -> update the avl and compare/swap
-      gpr_avl updated =
-          gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key),
-                      GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"));
+      gpr_avl updated = gpr_avl_add(
+          gpr_avl_ref(index, exec_ctx), subchannel_key_copy(key),
+          GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"), exec_ctx);
 
       // it may happen (but it's expected to be unlikely)
       // that some other thread has changed the index:
@@ -198,13 +182,11 @@
       }
       gpr_mu_unlock(&g_mu);
 
-      gpr_avl_unref(updated);
+      gpr_avl_unref(updated, exec_ctx);
     }
-    gpr_avl_unref(index);
+    gpr_avl_unref(index, exec_ctx);
   }
 
-  leave_ctx(exec_ctx);
-
   if (need_to_unref_constructed) {
     GRPC_SUBCHANNEL_UNREF(exec_ctx, constructed, "index_register");
   }
@@ -215,27 +197,26 @@
 void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
                                       grpc_subchannel_key *key,
                                       grpc_subchannel *constructed) {
-  enter_ctx(exec_ctx);
-
   bool done = false;
   while (!done) {
     // Compare and swap loop:
     // - take a reference to the current index
     gpr_mu_lock(&g_mu);
-    gpr_avl index = gpr_avl_ref(g_subchannel_index);
+    gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx);
     gpr_mu_unlock(&g_mu);
 
     // Check to see if this key still refers to the previously
     // registered subchannel
-    grpc_subchannel *c = gpr_avl_get(index, key);
+    grpc_subchannel *c = gpr_avl_get(index, key, exec_ctx);
     if (c != constructed) {
-      gpr_avl_unref(index);
+      gpr_avl_unref(index, exec_ctx);
       break;
     }
 
     // compare and swap the update (some other thread may have
     // mutated the index behind us)
-    gpr_avl updated = gpr_avl_remove(gpr_avl_ref(index), key);
+    gpr_avl updated =
+        gpr_avl_remove(gpr_avl_ref(index, exec_ctx), key, exec_ctx);
 
     gpr_mu_lock(&g_mu);
     if (index.root == g_subchannel_index.root) {
@@ -244,9 +225,11 @@
     }
     gpr_mu_unlock(&g_mu);
 
-    gpr_avl_unref(updated);
-    gpr_avl_unref(index);
+    gpr_avl_unref(updated, exec_ctx);
+    gpr_avl_unref(index, exec_ctx);
   }
+}
 
-  leave_ctx(exec_ctx);
+void grpc_subchannel_index_test_only_set_force_creation(bool force_creation) {
+  g_force_creation = force_creation;
 }
diff --git a/src/core/ext/filters/client_channel/subchannel_index.h b/src/core/ext/filters/client_channel/subchannel_index.h
index e303bfa..98d882a 100644
--- a/src/core/ext/filters/client_channel/subchannel_index.h
+++ b/src/core/ext/filters/client_channel/subchannel_index.h
@@ -59,4 +59,16 @@
 /** Shutdown the subchannel index (global) */
 void grpc_subchannel_index_shutdown(void);
 
+/** \em TEST ONLY.
+ * If \a force_creation is true, all key comparisons will be false, resulting in
+ * new subchannels always being created. Otherwise, the keys will be compared as
+ * usual.
+ *
+ * This function is *not* threadsafe on purpose: it should *only* be used in
+ * test code.
+ *
+ * Tests using this function \em MUST run tests with and without \a
+ * force_creation set. */
+void grpc_subchannel_index_test_only_set_force_creation(bool force_creation);
+
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */
diff --git a/src/core/ext/filters/http/client/http_client_filter.c b/src/core/ext/filters/http/client/http_client_filter.c
index 90f0aed..3ca01a4 100644
--- a/src/core/ext/filters/http/client/http_client_filter.c
+++ b/src/core/ext/filters/http/client/http_client_filter.c
@@ -36,41 +36,29 @@
 static const size_t kMaxPayloadSizeForGet = 2048;
 
 typedef struct call_data {
+  // State for handling send_initial_metadata ops.
   grpc_linked_mdelem method;
   grpc_linked_mdelem scheme;
   grpc_linked_mdelem authority;
   grpc_linked_mdelem te_trailers;
   grpc_linked_mdelem content_type;
   grpc_linked_mdelem user_agent;
-
+  // State for handling recv_initial_metadata ops.
   grpc_metadata_batch *recv_initial_metadata;
+  grpc_closure *original_recv_initial_metadata_ready;
+  grpc_closure recv_initial_metadata_ready;
+  // State for handling recv_trailing_metadata ops.
   grpc_metadata_batch *recv_trailing_metadata;
-  uint8_t *payload_bytes;
-
-  /* Vars to read data off of send_message */
-  grpc_transport_stream_op_batch *send_op;
-  uint32_t send_length;
-  uint32_t send_flags;
-  grpc_slice incoming_slice;
-  grpc_slice_buffer_stream replacement_stream;
-  grpc_slice_buffer slices;
-  /* flag that indicates that all slices of send_messages aren't availble */
-  bool send_message_blocked;
-
-  /** Closure to call when finished with the hc_on_recv hook */
-  grpc_closure *on_done_recv_initial_metadata;
-  grpc_closure *on_done_recv_trailing_metadata;
-  grpc_closure *on_complete;
-  grpc_closure *post_send;
-
-  /** Receive closures are chained: we inject this closure as the on_done_recv
-      up-call on transport_op, and remember to call our on_done_recv member
-      after handling it. */
-  grpc_closure hc_on_recv_initial_metadata;
-  grpc_closure hc_on_recv_trailing_metadata;
-  grpc_closure hc_on_complete;
-  grpc_closure got_slice;
-  grpc_closure send_done;
+  grpc_closure *original_recv_trailing_metadata_on_complete;
+  grpc_closure recv_trailing_metadata_on_complete;
+  // State for handling send_message ops.
+  grpc_transport_stream_op_batch *send_message_batch;
+  size_t send_message_bytes_read;
+  grpc_byte_stream_cache send_message_cache;
+  grpc_caching_byte_stream send_message_caching_stream;
+  grpc_closure on_send_message_next_done;
+  grpc_closure *original_send_message_on_complete;
+  grpc_closure send_message_on_complete;
 } call_data;
 
 typedef struct channel_data {
@@ -148,7 +136,7 @@
   return GRPC_ERROR_NONE;
 }
 
-static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
+static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
                                         void *user_data, grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
@@ -158,11 +146,13 @@
   } else {
     GRPC_ERROR_REF(error);
   }
-  GRPC_CLOSURE_RUN(exec_ctx, calld->on_done_recv_initial_metadata, error);
+  GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_initial_metadata_ready,
+                   error);
 }
 
-static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
-                                         void *user_data, grpc_error *error) {
+static void recv_trailing_metadata_on_complete(grpc_exec_ctx *exec_ctx,
+                                               void *user_data,
+                                               grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
   if (error == GRPC_ERROR_NONE) {
@@ -171,25 +161,131 @@
   } else {
     GRPC_ERROR_REF(error);
   }
-  GRPC_CLOSURE_RUN(exec_ctx, calld->on_done_recv_trailing_metadata, error);
+  GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_trailing_metadata_on_complete,
+                   error);
 }
 
-static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
-                           grpc_error *error) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  if (calld->payload_bytes) {
-    gpr_free(calld->payload_bytes);
-    calld->payload_bytes = NULL;
+static void send_message_on_complete(grpc_exec_ctx *exec_ctx, void *arg,
+                                     grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
+  grpc_byte_stream_cache_destroy(exec_ctx, &calld->send_message_cache);
+  GRPC_CLOSURE_RUN(exec_ctx, calld->original_send_message_on_complete,
+                   GRPC_ERROR_REF(error));
+}
+
+// Pulls a slice from the send_message byte stream, updating
+// calld->send_message_bytes_read.
+static grpc_error *pull_slice_from_send_message(grpc_exec_ctx *exec_ctx,
+                                                call_data *calld) {
+  grpc_slice incoming_slice;
+  grpc_error *error = grpc_byte_stream_pull(
+      exec_ctx, &calld->send_message_caching_stream.base, &incoming_slice);
+  if (error == GRPC_ERROR_NONE) {
+    calld->send_message_bytes_read += GRPC_SLICE_LENGTH(incoming_slice);
+    grpc_slice_unref_internal(exec_ctx, incoming_slice);
   }
-  calld->on_complete->cb(exec_ctx, calld->on_complete->cb_arg, error);
+  return error;
 }
 
-static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
-  grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &calld->slices);
-  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
+// Reads as many slices as possible from the send_message byte stream.
+// Upon successful return, if calld->send_message_bytes_read ==
+// calld->send_message_caching_stream.base.length, then we have completed
+// reading from the byte stream; otherwise, an async read has been dispatched
+// and on_send_message_next_done() will be invoked when it is complete.
+static grpc_error *read_all_available_send_message_data(grpc_exec_ctx *exec_ctx,
+                                                        call_data *calld) {
+  while (grpc_byte_stream_next(exec_ctx,
+                               &calld->send_message_caching_stream.base,
+                               ~(size_t)0, &calld->on_send_message_next_done)) {
+    grpc_error *error = pull_slice_from_send_message(exec_ctx, calld);
+    if (error != GRPC_ERROR_NONE) return error;
+    if (calld->send_message_bytes_read ==
+        calld->send_message_caching_stream.base.length) {
+      break;
+    }
+  }
+  return GRPC_ERROR_NONE;
+}
+
+// Async callback for grpc_byte_stream_next().
+static void on_send_message_next_done(grpc_exec_ctx *exec_ctx, void *arg,
+                                      grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
+  if (error != GRPC_ERROR_NONE) {
+    grpc_transport_stream_op_batch_finish_with_failure(
+        exec_ctx, calld->send_message_batch, error);
+    return;
+  }
+  error = pull_slice_from_send_message(exec_ctx, calld);
+  if (error != GRPC_ERROR_NONE) {
+    grpc_transport_stream_op_batch_finish_with_failure(
+        exec_ctx, calld->send_message_batch, error);
+    return;
+  }
+  // There may or may not be more to read, but we don't care.  If we got
+  // here, then we know that all of the data was not available
+  // synchronously, so we were not able to do a cached call.  Instead,
+  // we just reset the byte stream and then send down the batch as-is.
+  grpc_caching_byte_stream_reset(&calld->send_message_caching_stream);
+  grpc_call_next_op(exec_ctx, elem, calld->send_message_batch);
+}
+
+static char *slice_buffer_to_string(grpc_slice_buffer *slice_buffer) {
+  char *payload_bytes = gpr_malloc(slice_buffer->length + 1);
+  size_t offset = 0;
+  for (size_t i = 0; i < slice_buffer->count; ++i) {
+    memcpy(payload_bytes + offset,
+           GRPC_SLICE_START_PTR(slice_buffer->slices[i]),
+           GRPC_SLICE_LENGTH(slice_buffer->slices[i]));
+    offset += GRPC_SLICE_LENGTH(slice_buffer->slices[i]);
+  }
+  *(payload_bytes + offset) = '\0';
+  return payload_bytes;
+}
+
+// Modifies the path entry in the batch's send_initial_metadata to
+// append the base64-encoded query for a GET request.
+static grpc_error *update_path_for_get(grpc_exec_ctx *exec_ctx,
+                                       grpc_call_element *elem,
+                                       grpc_transport_stream_op_batch *batch) {
+  call_data *calld = (call_data *)elem->call_data;
+  grpc_slice path_slice =
+      GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata
+                       ->idx.named.path->md);
+  /* sum up individual component's lengths and allocate enough memory to
+   * hold combined path+query */
+  size_t estimated_len = GRPC_SLICE_LENGTH(path_slice);
+  estimated_len++; /* for the '?' */
+  estimated_len += grpc_base64_estimate_encoded_size(
+      batch->payload->send_message.send_message->length, true /* url_safe */,
+      false /* multi_line */);
+  grpc_slice path_with_query_slice = GRPC_SLICE_MALLOC(estimated_len);
+  /* memcopy individual pieces into this slice */
+  char *write_ptr = (char *)GRPC_SLICE_START_PTR(path_with_query_slice);
+  char *original_path = (char *)GRPC_SLICE_START_PTR(path_slice);
+  memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice));
+  write_ptr += GRPC_SLICE_LENGTH(path_slice);
+  *write_ptr++ = '?';
+  char *payload_bytes =
+      slice_buffer_to_string(&calld->send_message_cache.cache_buffer);
+  grpc_base64_encode_core((char *)write_ptr, payload_bytes,
+                          batch->payload->send_message.send_message->length,
+                          true /* url_safe */, false /* multi_line */);
+  gpr_free(payload_bytes);
+  /* remove trailing unused memory and add trailing 0 to terminate string */
+  char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice);
+  /* safe to use strlen since base64_encode will always add '\0' */
+  path_with_query_slice =
+      grpc_slice_sub_no_ref(path_with_query_slice, 0, strlen(t));
+  /* substitute previous path with the new path+query */
+  grpc_mdelem mdelem_path_and_query =
+      grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice);
+  grpc_metadata_batch *b =
+      batch->payload->send_initial_metadata.send_initial_metadata;
+  return grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
+                                        mdelem_path_and_query);
 }
 
 static void remove_if_present(grpc_exec_ctx *exec_ctx,
@@ -200,273 +296,153 @@
   }
 }
 
-static void continue_send_message(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  uint8_t *wrptr = calld->payload_bytes;
-  while (grpc_byte_stream_next(
-      exec_ctx, calld->send_op->payload->send_message.send_message, ~(size_t)0,
-      &calld->got_slice)) {
-    grpc_byte_stream_pull(exec_ctx,
-                          calld->send_op->payload->send_message.send_message,
-                          &calld->incoming_slice);
-    if (GRPC_SLICE_LENGTH(calld->incoming_slice) > 0) {
-      memcpy(wrptr, GRPC_SLICE_START_PTR(calld->incoming_slice),
-             GRPC_SLICE_LENGTH(calld->incoming_slice));
-    }
-    wrptr += GRPC_SLICE_LENGTH(calld->incoming_slice);
-    grpc_slice_buffer_add(&calld->slices, calld->incoming_slice);
-    if (calld->send_length == calld->slices.length) {
-      calld->send_message_blocked = false;
-      break;
-    }
-  }
-}
-
-static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
-  calld->send_message_blocked = false;
-  if (GRPC_ERROR_NONE !=
-      grpc_byte_stream_pull(exec_ctx,
-                            calld->send_op->payload->send_message.send_message,
-                            &calld->incoming_slice)) {
-    /* Should never reach here */
-    abort();
-  }
-  grpc_slice_buffer_add(&calld->slices, calld->incoming_slice);
-  if (calld->send_length == calld->slices.length) {
-    /* Pass down the original send_message op that was blocked.*/
-    grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
-                                  calld->send_flags);
-    calld->send_op->payload->send_message.send_message =
-        &calld->replacement_stream.base;
-    calld->post_send = calld->send_op->on_complete;
-    calld->send_op->on_complete = &calld->send_done;
-    grpc_call_next_op(exec_ctx, elem, calld->send_op);
-  } else {
-    continue_send_message(exec_ctx, elem);
-  }
-}
-
-static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx,
-                                grpc_call_element *elem,
-                                grpc_transport_stream_op_batch *op) {
-  /* grab pointers to our data from the call element */
+static void hc_start_transport_stream_op_batch(
+    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+    grpc_transport_stream_op_batch *batch) {
   call_data *calld = elem->call_data;
   channel_data *channeld = elem->channel_data;
-  grpc_error *error;
+  GPR_TIMER_BEGIN("hc_start_transport_stream_op_batch", 0);
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, batch);
 
-  if (op->send_initial_metadata) {
-    /* Decide which HTTP VERB to use. We use GET if the request is marked
-    cacheable, and the operation contains both initial metadata and send
-    message, and the payload is below the size threshold, and all the data
-    for this request is immediately available. */
+  if (batch->recv_initial_metadata) {
+    /* substitute our callback for the higher callback */
+    calld->recv_initial_metadata =
+        batch->payload->recv_initial_metadata.recv_initial_metadata;
+    calld->original_recv_initial_metadata_ready =
+        batch->payload->recv_initial_metadata.recv_initial_metadata_ready;
+    batch->payload->recv_initial_metadata.recv_initial_metadata_ready =
+        &calld->recv_initial_metadata_ready;
+  }
+
+  if (batch->recv_trailing_metadata) {
+    /* substitute our callback for the higher callback */
+    calld->recv_trailing_metadata =
+        batch->payload->recv_trailing_metadata.recv_trailing_metadata;
+    calld->original_recv_trailing_metadata_on_complete = batch->on_complete;
+    batch->on_complete = &calld->recv_trailing_metadata_on_complete;
+  }
+
+  grpc_error *error = GRPC_ERROR_NONE;
+  bool batch_will_be_handled_asynchronously = false;
+  if (batch->send_initial_metadata) {
+    // Decide which HTTP VERB to use. We use GET if the request is marked
+    // cacheable, and the operation contains both initial metadata and send
+    // message, and the payload is below the size threshold, and all the data
+    // for this request is immediately available.
     grpc_mdelem method = GRPC_MDELEM_METHOD_POST;
-    if (op->send_message &&
-        (op->payload->send_initial_metadata.send_initial_metadata_flags &
+    if (batch->send_message &&
+        (batch->payload->send_initial_metadata.send_initial_metadata_flags &
          GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) &&
-        op->payload->send_message.send_message->length <
+        batch->payload->send_message.send_message->length <
             channeld->max_payload_size_for_get) {
-      method = GRPC_MDELEM_METHOD_GET;
-      /* The following write to calld->send_message_blocked isn't racy with
-      reads in hc_start_transport_op (which deals with SEND_MESSAGE ops) because
-      being here means ops->send_message is not NULL, which is primarily
-      guarding the read there. */
-      calld->send_message_blocked = true;
-    } else if (op->payload->send_initial_metadata.send_initial_metadata_flags &
+      calld->send_message_bytes_read = 0;
+      grpc_byte_stream_cache_init(&calld->send_message_cache,
+                                  batch->payload->send_message.send_message);
+      grpc_caching_byte_stream_init(&calld->send_message_caching_stream,
+                                    &calld->send_message_cache);
+      batch->payload->send_message.send_message =
+          &calld->send_message_caching_stream.base;
+      calld->original_send_message_on_complete = batch->on_complete;
+      batch->on_complete = &calld->send_message_on_complete;
+      calld->send_message_batch = batch;
+      error = read_all_available_send_message_data(exec_ctx, calld);
+      if (error != GRPC_ERROR_NONE) goto done;
+      // If all the data has been read, then we can use GET.
+      if (calld->send_message_bytes_read ==
+          calld->send_message_caching_stream.base.length) {
+        method = GRPC_MDELEM_METHOD_GET;
+        error = update_path_for_get(exec_ctx, elem, batch);
+        if (error != GRPC_ERROR_NONE) goto done;
+        batch->send_message = false;
+        grpc_byte_stream_destroy(exec_ctx,
+                                 &calld->send_message_caching_stream.base);
+      } else {
+        // Not all data is available.  The batch will be sent down
+        // asynchronously in on_send_message_next_done().
+        batch_will_be_handled_asynchronously = true;
+        // Fall back to POST.
+        gpr_log(GPR_DEBUG,
+                "Request is marked Cacheable but not all data is available.  "
+                "Falling back to POST");
+      }
+    } else if (batch->payload->send_initial_metadata
+                   .send_initial_metadata_flags &
                GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) {
       method = GRPC_MDELEM_METHOD_PUT;
     }
 
-    /* Attempt to read the data from send_message and create a header field. */
-    if (grpc_mdelem_eq(method, GRPC_MDELEM_METHOD_GET)) {
-      /* allocate memory to hold the entire payload */
-      calld->payload_bytes =
-          gpr_malloc(op->payload->send_message.send_message->length);
-
-      /* read slices of send_message and copy into payload_bytes */
-      calld->send_op = op;
-      calld->send_length = op->payload->send_message.send_message->length;
-      calld->send_flags = op->payload->send_message.send_message->flags;
-      continue_send_message(exec_ctx, elem);
-
-      if (calld->send_message_blocked == false) {
-        /* when all the send_message data is available, then modify the path
-         * MDELEM by appending base64 encoded query to the path */
-        const int k_url_safe = 1;
-        const int k_multi_line = 0;
-        const unsigned char k_query_separator = '?';
-
-        grpc_slice path_slice =
-            GRPC_MDVALUE(op->payload->send_initial_metadata
-                             .send_initial_metadata->idx.named.path->md);
-        /* sum up individual component's lengths and allocate enough memory to
-         * hold combined path+query */
-        size_t estimated_len = GRPC_SLICE_LENGTH(path_slice);
-        estimated_len++; /* for the '?' */
-        estimated_len += grpc_base64_estimate_encoded_size(
-            op->payload->send_message.send_message->length, k_url_safe,
-            k_multi_line);
-        grpc_slice path_with_query_slice = GRPC_SLICE_MALLOC(estimated_len);
-
-        /* memcopy individual pieces into this slice */
-        uint8_t *write_ptr =
-            (uint8_t *)GRPC_SLICE_START_PTR(path_with_query_slice);
-        uint8_t *original_path = (uint8_t *)GRPC_SLICE_START_PTR(path_slice);
-        memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice));
-        write_ptr += GRPC_SLICE_LENGTH(path_slice);
-
-        *write_ptr = k_query_separator;
-        write_ptr++; /* for the '?' */
-
-        grpc_base64_encode_core((char *)write_ptr, calld->payload_bytes,
-                                op->payload->send_message.send_message->length,
-                                k_url_safe, k_multi_line);
-
-        /* remove trailing unused memory and add trailing 0 to terminate string
-         */
-        char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice);
-        /* safe to use strlen since base64_encode will always add '\0' */
-        path_with_query_slice =
-            grpc_slice_sub_no_ref(path_with_query_slice, 0, strlen(t));
-
-        /* substitute previous path with the new path+query */
-        grpc_mdelem mdelem_path_and_query = grpc_mdelem_from_slices(
-            exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice);
-        grpc_metadata_batch *b =
-            op->payload->send_initial_metadata.send_initial_metadata;
-        error = grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
-                                               mdelem_path_and_query);
-        if (error != GRPC_ERROR_NONE) return error;
-
-        calld->on_complete = op->on_complete;
-        op->on_complete = &calld->hc_on_complete;
-        op->send_message = false;
-      } else {
-        /* Not all data is available. Fall back to POST. */
-        gpr_log(GPR_DEBUG,
-                "Request is marked Cacheable but not all data is available.\
-                            Falling back to POST");
-        method = GRPC_MDELEM_METHOD_POST;
-      }
-    }
-
-    remove_if_present(exec_ctx,
-                      op->payload->send_initial_metadata.send_initial_metadata,
-                      GRPC_BATCH_METHOD);
-    remove_if_present(exec_ctx,
-                      op->payload->send_initial_metadata.send_initial_metadata,
-                      GRPC_BATCH_SCHEME);
-    remove_if_present(exec_ctx,
-                      op->payload->send_initial_metadata.send_initial_metadata,
-                      GRPC_BATCH_TE);
-    remove_if_present(exec_ctx,
-                      op->payload->send_initial_metadata.send_initial_metadata,
-                      GRPC_BATCH_CONTENT_TYPE);
-    remove_if_present(exec_ctx,
-                      op->payload->send_initial_metadata.send_initial_metadata,
-                      GRPC_BATCH_USER_AGENT);
+    remove_if_present(
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
+        GRPC_BATCH_METHOD);
+    remove_if_present(
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
+        GRPC_BATCH_SCHEME);
+    remove_if_present(
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
+        GRPC_BATCH_TE);
+    remove_if_present(
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
+        GRPC_BATCH_CONTENT_TYPE);
+    remove_if_present(
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
+        GRPC_BATCH_USER_AGENT);
 
     /* Send : prefixed headers, which have to be before any application
        layer headers. */
     error = grpc_metadata_batch_add_head(
-        exec_ctx, op->payload->send_initial_metadata.send_initial_metadata,
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->method, method);
-    if (error != GRPC_ERROR_NONE) return error;
+    if (error != GRPC_ERROR_NONE) goto done;
     error = grpc_metadata_batch_add_head(
-        exec_ctx, op->payload->send_initial_metadata.send_initial_metadata,
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->scheme, channeld->static_scheme);
-    if (error != GRPC_ERROR_NONE) return error;
+    if (error != GRPC_ERROR_NONE) goto done;
     error = grpc_metadata_batch_add_tail(
-        exec_ctx, op->payload->send_initial_metadata.send_initial_metadata,
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS);
-    if (error != GRPC_ERROR_NONE) return error;
+    if (error != GRPC_ERROR_NONE) goto done;
     error = grpc_metadata_batch_add_tail(
-        exec_ctx, op->payload->send_initial_metadata.send_initial_metadata,
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
-    if (error != GRPC_ERROR_NONE) return error;
+    if (error != GRPC_ERROR_NONE) goto done;
     error = grpc_metadata_batch_add_tail(
-        exec_ctx, op->payload->send_initial_metadata.send_initial_metadata,
+        exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata,
         &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent));
-    if (error != GRPC_ERROR_NONE) return error;
+    if (error != GRPC_ERROR_NONE) goto done;
   }
 
-  if (op->recv_initial_metadata) {
-    /* substitute our callback for the higher callback */
-    calld->recv_initial_metadata =
-        op->payload->recv_initial_metadata.recv_initial_metadata;
-    calld->on_done_recv_initial_metadata =
-        op->payload->recv_initial_metadata.recv_initial_metadata_ready;
-    op->payload->recv_initial_metadata.recv_initial_metadata_ready =
-        &calld->hc_on_recv_initial_metadata;
-  }
-
-  if (op->recv_trailing_metadata) {
-    /* substitute our callback for the higher callback */
-    calld->recv_trailing_metadata =
-        op->payload->recv_trailing_metadata.recv_trailing_metadata;
-    calld->on_done_recv_trailing_metadata = op->on_complete;
-    op->on_complete = &calld->hc_on_recv_trailing_metadata;
-  }
-
-  return GRPC_ERROR_NONE;
-}
-
-static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_transport_stream_op_batch *op) {
-  GPR_TIMER_BEGIN("hc_start_transport_op", 0);
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  grpc_error *error = hc_mutate_op(exec_ctx, elem, op);
+done:
   if (error != GRPC_ERROR_NONE) {
-    grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
-  } else {
-    call_data *calld = elem->call_data;
-    if (op->send_message && calld->send_message_blocked) {
-      /* Don't forward the op. send_message contains slices that aren't ready
-         yet. The call will be forwarded by the op_complete of slice read call.
-      */
-    } else {
-      grpc_call_next_op(exec_ctx, elem, op);
-    }
+    grpc_transport_stream_op_batch_finish_with_failure(
+        exec_ctx, calld->send_message_batch, error);
+  } else if (!batch_will_be_handled_asynchronously) {
+    grpc_call_next_op(exec_ctx, elem, batch);
   }
-  GPR_TIMER_END("hc_start_transport_op", 0);
+  GPR_TIMER_END("hc_start_transport_stream_op_batch", 0);
 }
 
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
                                   const grpc_call_element_args *args) {
-  call_data *calld = elem->call_data;
-  calld->on_done_recv_initial_metadata = NULL;
-  calld->on_done_recv_trailing_metadata = NULL;
-  calld->on_complete = NULL;
-  calld->payload_bytes = NULL;
-  calld->send_message_blocked = false;
-  grpc_slice_buffer_init(&calld->slices);
-  GRPC_CLOSURE_INIT(&calld->hc_on_recv_initial_metadata,
-                    hc_on_recv_initial_metadata, elem,
+  call_data *calld = (call_data *)elem->call_data;
+  GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
+                    recv_initial_metadata_ready, elem,
                     grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&calld->hc_on_recv_trailing_metadata,
-                    hc_on_recv_trailing_metadata, elem,
+  GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_on_complete,
+                    recv_trailing_metadata_on_complete, elem,
                     grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&calld->hc_on_complete, hc_on_complete, elem,
-                    grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&calld->got_slice, got_slice, elem,
-                    grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&calld->send_done, send_done, elem,
-                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete,
+                    elem, grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&calld->on_send_message_next_done,
+                    on_send_message_next_done, elem, grpc_schedule_on_exec_ctx);
   return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
 static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
                               const grpc_call_final_info *final_info,
-                              grpc_closure *ignored) {
-  call_data *calld = elem->call_data;
-  grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);
-}
+                              grpc_closure *ignored) {}
 
 static grpc_mdelem scheme_from_args(const grpc_channel_args *args) {
   unsigned i;
@@ -580,7 +556,7 @@
 }
 
 const grpc_channel_filter grpc_http_client_filter = {
-    hc_start_transport_op,
+    hc_start_transport_stream_op_batch,
     grpc_channel_next_op,
     sizeof(call_data),
     init_call_elem,
diff --git a/src/core/ext/filters/http/http_filters_plugin.c b/src/core/ext/filters/http/http_filters_plugin.c
index 3e4ec01..a5c1b92 100644
--- a/src/core/ext/filters/http/http_filters_plugin.c
+++ b/src/core/ext/filters/http/http_filters_plugin.c
@@ -65,7 +65,7 @@
 }
 
 void grpc_http_filters_init(void) {
-  grpc_register_tracer("compression", &grpc_compression_trace);
+  grpc_register_tracer(&grpc_compression_trace);
   grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
                                    maybe_add_optional_filter, &compress_filter);
diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.c b/src/core/ext/filters/http/message_compress/message_compress_filter.c
index 71a8bc5..20a3488 100644
--- a/src/core/ext/filters/http/message_compress/message_compress_filter.c
+++ b/src/core/ext/filters/http/message_compress/message_compress_filter.c
@@ -61,14 +61,11 @@
      pointer | CANCELLED_BIT - request was cancelled with error pointed to */
   gpr_atm send_initial_metadata_state;
 
-  grpc_transport_stream_op_batch *send_op;
-  uint32_t send_length;
-  uint32_t send_flags;
-  grpc_slice incoming_slice;
+  grpc_transport_stream_op_batch *send_message_batch;
   grpc_slice_buffer_stream replacement_stream;
-  grpc_closure *post_send;
-  grpc_closure send_done;
-  grpc_closure got_slice;
+  grpc_closure *original_send_message_on_complete;
+  grpc_closure send_message_on_complete;
+  grpc_closure on_send_message_next_done;
 } call_data;
 
 typedef struct channel_data {
@@ -164,24 +161,25 @@
   return error;
 }
 
-static void continue_send_message(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem);
-
-static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
+static void send_message_on_complete(grpc_exec_ctx *exec_ctx, void *arg,
+                                     grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
   grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &calld->slices);
-  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
+  GRPC_CLOSURE_RUN(exec_ctx, calld->original_send_message_on_complete,
+                   GRPC_ERROR_REF(error));
 }
 
 static void finish_send_message(grpc_exec_ctx *exec_ctx,
                                 grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
-  int did_compress;
+  call_data *calld = (call_data *)elem->call_data;
+  // Compress the data if appropriate.
   grpc_slice_buffer tmp;
   grpc_slice_buffer_init(&tmp);
-  did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm,
-                                   &calld->slices, &tmp);
+  uint32_t send_flags =
+      calld->send_message_batch->payload->send_message.send_message->flags;
+  const bool did_compress = grpc_msg_compress(
+      exec_ctx, calld->compression_algorithm, &calld->slices, &tmp);
   if (did_compress) {
     if (GRPC_TRACER_ON(grpc_compression_trace)) {
       char *algo_name;
@@ -195,7 +193,7 @@
               algo_name, before_size, after_size, 100 * savings_ratio);
     }
     grpc_slice_buffer_swap(&calld->slices, &tmp);
-    calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
+    send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
   } else {
     if (GRPC_TRACER_ON(grpc_compression_trace)) {
       char *algo_name;
@@ -207,83 +205,118 @@
               algo_name, calld->slices.length);
     }
   }
-
   grpc_slice_buffer_destroy_internal(exec_ctx, &tmp);
-
+  // Swap out the original byte stream with our new one and send the
+  // batch down.
+  grpc_byte_stream_destroy(
+      exec_ctx, calld->send_message_batch->payload->send_message.send_message);
   grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
-                                calld->send_flags);
-  calld->send_op->payload->send_message.send_message =
+                                send_flags);
+  calld->send_message_batch->payload->send_message.send_message =
       &calld->replacement_stream.base;
-  calld->post_send = calld->send_op->on_complete;
-  calld->send_op->on_complete = &calld->send_done;
-
-  grpc_call_next_op(exec_ctx, elem, calld->send_op);
+  calld->original_send_message_on_complete =
+      calld->send_message_batch->on_complete;
+  calld->send_message_batch->on_complete = &calld->send_message_on_complete;
+  grpc_call_next_op(exec_ctx, elem, calld->send_message_batch);
 }
 
-static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
-  grpc_call_element *elem = elemp;
-  call_data *calld = elem->call_data;
-  if (GRPC_ERROR_NONE !=
-      grpc_byte_stream_pull(exec_ctx,
-                            calld->send_op->payload->send_message.send_message,
-                            &calld->incoming_slice)) {
-    /* Should never reach here */
-    abort();
+// Pulls a slice from the send_message byte stream and adds it to calld->slices.
+static grpc_error *pull_slice_from_send_message(grpc_exec_ctx *exec_ctx,
+                                                call_data *calld) {
+  grpc_slice incoming_slice;
+  grpc_error *error = grpc_byte_stream_pull(
+      exec_ctx, calld->send_message_batch->payload->send_message.send_message,
+      &incoming_slice);
+  if (error == GRPC_ERROR_NONE) {
+    grpc_slice_buffer_add(&calld->slices, incoming_slice);
   }
-  grpc_slice_buffer_add(&calld->slices, calld->incoming_slice);
-  if (calld->send_length == calld->slices.length) {
-    finish_send_message(exec_ctx, elem);
-  } else {
-    continue_send_message(exec_ctx, elem);
-  }
+  return error;
 }
 
-static void continue_send_message(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem) {
-  call_data *calld = elem->call_data;
+// Reads as many slices as possible from the send_message byte stream.
+// If all data has been read, invokes finish_send_message().  Otherwise,
+// an async call to grpc_byte_stream_next() has been started, which will
+// eventually result in calling on_send_message_next_done().
+static grpc_error *continue_reading_send_message(grpc_exec_ctx *exec_ctx,
+                                                 grpc_call_element *elem) {
+  call_data *calld = (call_data *)elem->call_data;
   while (grpc_byte_stream_next(
-      exec_ctx, calld->send_op->payload->send_message.send_message, ~(size_t)0,
-      &calld->got_slice)) {
-    grpc_byte_stream_pull(exec_ctx,
-                          calld->send_op->payload->send_message.send_message,
-                          &calld->incoming_slice);
-    grpc_slice_buffer_add(&calld->slices, calld->incoming_slice);
-    if (calld->send_length == calld->slices.length) {
+      exec_ctx, calld->send_message_batch->payload->send_message.send_message,
+      ~(size_t)0, &calld->on_send_message_next_done)) {
+    grpc_error *error = pull_slice_from_send_message(exec_ctx, calld);
+    if (error != GRPC_ERROR_NONE) return error;
+    if (calld->slices.length ==
+        calld->send_message_batch->payload->send_message.send_message->length) {
       finish_send_message(exec_ctx, elem);
       break;
     }
   }
+  return GRPC_ERROR_NONE;
 }
 
-static void handle_send_message_batch(grpc_exec_ctx *exec_ctx,
-                                      grpc_call_element *elem,
-                                      grpc_transport_stream_op_batch *op,
-                                      bool has_compression_algorithm) {
-  call_data *calld = elem->call_data;
-  if (!skip_compression(elem, op->payload->send_message.send_message->flags,
+// Async callback for grpc_byte_stream_next().
+static void on_send_message_next_done(grpc_exec_ctx *exec_ctx, void *arg,
+                                      grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
+  if (error != GRPC_ERROR_NONE) goto fail;
+  error = pull_slice_from_send_message(exec_ctx, calld);
+  if (error != GRPC_ERROR_NONE) goto fail;
+  if (calld->slices.length ==
+      calld->send_message_batch->payload->send_message.send_message->length) {
+    finish_send_message(exec_ctx, elem);
+  } else {
+    // This will either finish reading all of the data and invoke
+    // finish_send_message(), or else it will make an async call to
+    // grpc_byte_stream_next(), which will eventually result in calling
+    // this function again.
+    error = continue_reading_send_message(exec_ctx, elem);
+    if (error != GRPC_ERROR_NONE) goto fail;
+  }
+  return;
+fail:
+  grpc_transport_stream_op_batch_finish_with_failure(
+      exec_ctx, calld->send_message_batch, error);
+}
+
+static void start_send_message_batch(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_element *elem,
+                                     grpc_transport_stream_op_batch *batch,
+                                     bool has_compression_algorithm) {
+  call_data *calld = (call_data *)elem->call_data;
+  if (!skip_compression(elem, batch->payload->send_message.send_message->flags,
                         has_compression_algorithm)) {
-    calld->send_op = op;
-    calld->send_length = op->payload->send_message.send_message->length;
-    calld->send_flags = op->payload->send_message.send_message->flags;
-    continue_send_message(exec_ctx, elem);
+    calld->send_message_batch = batch;
+    // This will either finish reading all of the data and invoke
+    // finish_send_message(), or else it will make an async call to
+    // grpc_byte_stream_next(), which will eventually result in calling
+    // on_send_message_next_done().
+    grpc_error *error = continue_reading_send_message(exec_ctx, elem);
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_batch_finish_with_failure(
+          exec_ctx, calld->send_message_batch, error);
+    }
   } else {
     /* pass control down the stack */
-    grpc_call_next_op(exec_ctx, elem, op);
+    grpc_call_next_op(exec_ctx, elem, batch);
   }
 }
 
 static void compress_start_transport_stream_op_batch(
     grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-    grpc_transport_stream_op_batch *op) {
+    grpc_transport_stream_op_batch *batch) {
   call_data *calld = elem->call_data;
 
   GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0);
 
-  if (op->cancel_stream) {
-    GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error);
+  if (batch->cancel_stream) {
+    // TODO(roth): As part of the upcoming call combiner work, change
+    // this to call grpc_byte_stream_shutdown() on the incoming byte
+    // stream, to cancel any in-flight calls to grpc_byte_stream_next().
+    GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
     gpr_atm cur = gpr_atm_full_xchg(
         &calld->send_initial_metadata_state,
-        CANCELLED_BIT | (gpr_atm)op->payload->cancel_stream.cancel_error);
+        CANCELLED_BIT | (gpr_atm)batch->payload->cancel_stream.cancel_error);
     switch (cur) {
       case HAS_COMPRESSION_ALGORITHM:
       case NO_COMPRESSION_ALGORITHM:
@@ -293,7 +326,7 @@
         if ((cur & CANCELLED_BIT) == 0) {
           grpc_transport_stream_op_batch_finish_with_failure(
               exec_ctx, (grpc_transport_stream_op_batch *)cur,
-              GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
+              GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error));
         } else {
           GRPC_ERROR_UNREF((grpc_error *)(cur & ~CANCELLED_BIT));
         }
@@ -301,14 +334,15 @@
     }
   }
 
-  if (op->send_initial_metadata) {
+  if (batch->send_initial_metadata) {
     bool has_compression_algorithm;
     grpc_error *error = process_send_initial_metadata(
         exec_ctx, elem,
-        op->payload->send_initial_metadata.send_initial_metadata,
+        batch->payload->send_initial_metadata.send_initial_metadata,
         &has_compression_algorithm);
     if (error != GRPC_ERROR_NONE) {
-      grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
+      grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch,
+                                                         error);
       return;
     }
     gpr_atm cur;
@@ -324,32 +358,32 @@
         goto retry_send_im;
       }
       if (cur != INITIAL_METADATA_UNSEEN) {
-        handle_send_message_batch(exec_ctx, elem,
-                                  (grpc_transport_stream_op_batch *)cur,
-                                  has_compression_algorithm);
+        start_send_message_batch(exec_ctx, elem,
+                                 (grpc_transport_stream_op_batch *)cur,
+                                 has_compression_algorithm);
       }
     }
   }
-  if (op->send_message) {
+  if (batch->send_message) {
     gpr_atm cur;
   retry_send:
     cur = gpr_atm_acq_load(&calld->send_initial_metadata_state);
     switch (cur) {
       case INITIAL_METADATA_UNSEEN:
         if (!gpr_atm_rel_cas(&calld->send_initial_metadata_state, cur,
-                             (gpr_atm)op)) {
+                             (gpr_atm)batch)) {
           goto retry_send;
         }
         break;
       case HAS_COMPRESSION_ALGORITHM:
       case NO_COMPRESSION_ALGORITHM:
-        handle_send_message_batch(exec_ctx, elem, op,
-                                  cur == HAS_COMPRESSION_ALGORITHM);
+        start_send_message_batch(exec_ctx, elem, batch,
+                                 cur == HAS_COMPRESSION_ALGORITHM);
         break;
       default:
         if (cur & CANCELLED_BIT) {
           grpc_transport_stream_op_batch_finish_with_failure(
-              exec_ctx, op,
+              exec_ctx, batch,
               GRPC_ERROR_REF((grpc_error *)(cur & ~CANCELLED_BIT)));
         } else {
           /* >1 send_message concurrently */
@@ -358,7 +392,7 @@
     }
   } else {
     /* pass control down the stack */
-    grpc_call_next_op(exec_ctx, elem, op);
+    grpc_call_next_op(exec_ctx, elem, batch);
   }
 
   GPR_TIMER_END("compress_start_transport_stream_op_batch", 0);
@@ -373,10 +407,10 @@
 
   /* initialize members */
   grpc_slice_buffer_init(&calld->slices);
-  GRPC_CLOSURE_INIT(&calld->got_slice, got_slice, elem,
-                    grpc_schedule_on_exec_ctx);
-  GRPC_CLOSURE_INIT(&calld->send_done, send_done, elem,
-                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&calld->on_send_message_next_done,
+                    on_send_message_next_done, elem, grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete,
+                    elem, grpc_schedule_on_exec_ctx);
 
   return GRPC_ERROR_NONE;
 }
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
index 6a8c814..78551df 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
@@ -21,10 +21,10 @@
 #include "src/core/lib/transport/metadata.h"
 
 void grpc_chttp2_plugin_init(void) {
-  grpc_register_tracer("http", &grpc_http_trace);
-  grpc_register_tracer("flowctl", &grpc_flowctl_trace);
+  grpc_register_tracer(&grpc_http_trace);
+  grpc_register_tracer(&grpc_flowctl_trace);
 #ifndef NDEBUG
-  grpc_register_tracer("chttp2_refcount", &grpc_trace_chttp2_refcount);
+  grpc_register_tracer(&grpc_trace_chttp2_refcount);
 #endif
 }
 
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index f790267..aabe7b4 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -33,6 +33,7 @@
 #include "src/core/ext/transport/chttp2/transport/internal.h"
 #include "src/core/ext/transport/chttp2/transport/varint.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/compression/stream_compression.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/timer.h"
@@ -74,11 +75,12 @@
     DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
 
 #define MAX_CLIENT_STREAM_ID 0x7fffffffu
-grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false);
-grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false, "http");
+grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false, "flowctl");
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_chttp2_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_chttp2_refcount =
+    GRPC_TRACER_INITIALIZER(false, "chttp2_refcount");
 #endif
 
 static const grpc_transport_vtable vtable;
@@ -112,11 +114,6 @@
                                    grpc_connectivity_state state,
                                    grpc_error *error, const char *reason);
 
-static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
-                                                     grpc_chttp2_transport *t,
-                                                     grpc_chttp2_stream *s,
-                                                     size_t max_size_hint,
-                                                     size_t have_already);
 static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
                                                 void *byte_stream,
                                                 grpc_error *error_ignored);
@@ -268,8 +265,9 @@
   t->endpoint_reading = 1;
   t->next_stream_id = is_client ? 1 : 2;
   t->is_client = is_client;
-  t->outgoing_window = DEFAULT_WINDOW;
-  t->incoming_window = DEFAULT_WINDOW;
+  t->flow_control.remote_window = DEFAULT_WINDOW;
+  t->flow_control.announced_window = DEFAULT_WINDOW;
+  t->flow_control.t = t;
   t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
   t->is_first_frame = true;
   grpc_connectivity_state_init(
@@ -708,6 +706,7 @@
     post_destructive_reclaimer(exec_ctx, t);
   }
 
+  s->flow_control.s = s;
   GPR_TIMER_END("init_stream", 0);
 
   return 0;
@@ -728,6 +727,14 @@
   grpc_slice_buffer_destroy_internal(exec_ctx,
                                      &s->unprocessed_incoming_frames_buffer);
   grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage);
+  if (s->compressed_data_buffer) {
+    grpc_slice_buffer_destroy_internal(exec_ctx, s->compressed_data_buffer);
+    gpr_free(s->compressed_data_buffer);
+  }
+  if (s->decompressed_data_buffer) {
+    grpc_slice_buffer_destroy_internal(exec_ctx, s->decompressed_data_buffer);
+    gpr_free(s->decompressed_data_buffer);
+  }
 
   grpc_chttp2_list_remove_stalled_by_transport(t, s);
   grpc_chttp2_list_remove_stalled_by_stream(t, s);
@@ -756,13 +763,7 @@
   GRPC_ERROR_UNREF(s->write_closed_error);
   GRPC_ERROR_UNREF(s->byte_stream_error);
 
-  if (s->incoming_window_delta > 0) {
-    GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(
-        "destroy", t, s, s->incoming_window_delta);
-  } else if (s->incoming_window_delta < 0) {
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(
-        "destroy", t, s, -s->incoming_window_delta);
-  }
+  grpc_chttp2_flowctl_destroy_stream(&t->flow_control, &s->flow_control);
 
   GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
 
@@ -778,6 +779,15 @@
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
   grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
 
+  if (s->stream_compression_ctx != NULL) {
+    grpc_stream_compression_context_destroy(s->stream_compression_ctx);
+    s->stream_compression_ctx = NULL;
+  }
+  if (s->stream_decompression_ctx != NULL) {
+    grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
+    s->stream_decompression_ctx = NULL;
+  }
+
   s->destroy_stream_arg = then_schedule_closure;
   GRPC_CLOSURE_SCHED(
       exec_ctx, GRPC_CLOSURE_INIT(&s->destroy_stream, destroy_stream_locked, s,
@@ -1171,6 +1181,7 @@
       return;  /* early out */
     }
     if (s->fetched_send_message_length == s->fetching_send_message->length) {
+      grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
       int64_t notify_offset = s->next_message_end_offset;
       if (notify_offset <= s->flow_controlled_bytes_written) {
         grpc_chttp2_complete_closure_step(
@@ -1193,9 +1204,14 @@
       return; /* early out */
     } else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
                                      UINT32_MAX, &s->complete_fetch_locked)) {
-      grpc_byte_stream_pull(exec_ctx, s->fetching_send_message,
-                            &s->fetching_slice);
-      add_fetched_slice_locked(exec_ctx, t, s);
+      grpc_error *error = grpc_byte_stream_pull(
+          exec_ctx, s->fetching_send_message, &s->fetching_slice);
+      if (error != GRPC_ERROR_NONE) {
+        grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
+        grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
+      } else {
+        add_fetched_slice_locked(exec_ctx, t, s);
+      }
     }
   }
 }
@@ -1212,10 +1228,9 @@
       continue_fetching_send_locked(exec_ctx, t, s);
     }
   }
-
   if (error != GRPC_ERROR_NONE) {
-    /* TODO(ctiller): what to do here */
-    abort();
+    grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
+    grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
   }
 }
 
@@ -1223,7 +1238,7 @@
 
 static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
                          bool is_client, bool is_initial) {
-  for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
+  for (grpc_linked_mdelem *md = md_batch->list.head; md != NULL;
        md = md->next) {
     char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
     char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
@@ -1360,8 +1375,8 @@
           "fetching_send_message_finished");
     } else {
       GPR_ASSERT(s->fetching_send_message == NULL);
-      uint8_t *frame_hdr =
-          grpc_slice_buffer_tiny_add(&s->flow_controlled_buffer, 5);
+      uint8_t *frame_hdr = grpc_slice_buffer_tiny_add(
+          &s->flow_controlled_buffer, GRPC_HEADER_SIZE_IN_BYTES);
       uint32_t flags = op_payload->send_message.send_message->flags;
       frame_hdr[0] = (flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0;
       size_t len = op_payload->send_message.send_message->length;
@@ -1452,14 +1467,16 @@
     s->recv_message_ready = op_payload->recv_message.recv_message_ready;
     s->recv_message = op_payload->recv_message.recv_message;
     if (s->id != 0) {
-      if (s->pending_byte_stream) {
+      if (!s->read_closed) {
         already_received = s->frame_storage.length;
-      } else {
-        already_received = s->frame_storage.length +
-                           s->unprocessed_incoming_frames_buffer.length;
+        grpc_chttp2_flowctl_incoming_bs_update(
+            &t->flow_control, &s->flow_control, GRPC_HEADER_SIZE_IN_BYTES,
+            already_received);
+        grpc_chttp2_act_on_flowctl_action(
+            exec_ctx,
+            grpc_chttp2_flowctl_get_action(&t->flow_control, &s->flow_control),
+            t, s);
       }
-      incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5,
-                                               already_received);
     }
     grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
   }
@@ -1696,10 +1713,43 @@
         if (s->unprocessed_incoming_frames_buffer.length == 0) {
           grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
                                  &s->frame_storage);
+          s->unprocessed_incoming_frames_decompressed = false;
         }
-        error = grpc_deframe_unprocessed_incoming_frames(
-            exec_ctx, &s->data_parser, s,
-            &s->unprocessed_incoming_frames_buffer, NULL, s->recv_message);
+        if (s->stream_compression_recv_enabled &&
+            !s->unprocessed_incoming_frames_decompressed) {
+          GPR_ASSERT(s->decompressed_data_buffer->length == 0);
+          bool end_of_context;
+          if (!s->stream_decompression_ctx) {
+            s->stream_decompression_ctx =
+                grpc_stream_compression_context_create(
+                    GRPC_STREAM_COMPRESSION_DECOMPRESS);
+          }
+          if (!grpc_stream_decompress(s->stream_decompression_ctx,
+                                      &s->unprocessed_incoming_frames_buffer,
+                                      s->decompressed_data_buffer, NULL,
+                                      GRPC_HEADER_SIZE_IN_BYTES,
+                                      &end_of_context)) {
+            grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
+                                                       &s->frame_storage);
+            grpc_slice_buffer_reset_and_unref_internal(
+                exec_ctx, &s->unprocessed_incoming_frames_buffer);
+            error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                "Stream decompression error.");
+          } else {
+            error = grpc_deframe_unprocessed_incoming_frames(
+                exec_ctx, &s->data_parser, s, s->decompressed_data_buffer, NULL,
+                s->recv_message);
+            if (end_of_context) {
+              grpc_stream_compression_context_destroy(
+                  s->stream_decompression_ctx);
+              s->stream_decompression_ctx = NULL;
+            }
+          }
+        } else {
+          error = grpc_deframe_unprocessed_incoming_frames(
+              exec_ctx, &s->data_parser, s,
+              &s->unprocessed_incoming_frames_buffer, NULL, s->recv_message);
+        }
         if (error != GRPC_ERROR_NONE) {
           s->seen_error = true;
           grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
@@ -1737,7 +1787,37 @@
     }
     bool pending_data = s->pending_byte_stream ||
                         s->unprocessed_incoming_frames_buffer.length > 0;
+    if (s->stream_compression_recv_enabled && s->read_closed &&
+        s->frame_storage.length > 0 &&
+        s->unprocessed_incoming_frames_buffer.length == 0 && !pending_data &&
+        !s->seen_error && s->recv_trailing_metadata_finished != NULL) {
+      /* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and
+       * maybe decompress the next 5 bytes in the stream. */
+      bool end_of_context;
+      if (!s->stream_decompression_ctx) {
+        s->stream_decompression_ctx = grpc_stream_compression_context_create(
+            GRPC_STREAM_COMPRESSION_DECOMPRESS);
+      }
+      if (!grpc_stream_decompress(s->stream_decompression_ctx,
+                                  &s->frame_storage,
+                                  &s->unprocessed_incoming_frames_buffer, NULL,
+                                  GRPC_HEADER_SIZE_IN_BYTES, &end_of_context)) {
+        grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &s->frame_storage);
+        grpc_slice_buffer_reset_and_unref_internal(
+            exec_ctx, &s->unprocessed_incoming_frames_buffer);
+        s->seen_error = true;
+      } else {
+        if (s->unprocessed_incoming_frames_buffer.length > 0) {
+          s->unprocessed_incoming_frames_decompressed = true;
+        }
+        if (end_of_context) {
+          grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
+          s->stream_decompression_ctx = NULL;
+        }
+      }
+    }
     if (s->read_closed && s->frame_storage.length == 0 &&
+        s->unprocessed_incoming_frames_buffer.length == 0 &&
         (!pending_data || s->seen_error) &&
         s->recv_trailing_metadata_finished != NULL) {
       grpc_chttp2_incoming_metadata_buffer_publish(
@@ -2146,6 +2226,37 @@
  * INPUT PROCESSING - PARSING
  */
 
+void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_flowctl_action action,
+                                       grpc_chttp2_transport *t,
+                                       grpc_chttp2_stream *s) {
+  switch (action.send_stream_update) {
+    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
+      break;
+    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
+      grpc_chttp2_become_writable(exec_ctx, t, s,
+                                  GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
+                                  "immediate stream flowctl");
+      break;
+    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
+      grpc_chttp2_become_writable(exec_ctx, t, s,
+                                  GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK,
+                                  "queue stream flowctl");
+      break;
+  }
+  switch (action.send_transport_update) {
+    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
+      break;
+    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
+      grpc_chttp2_initiate_write(exec_ctx, t, "immediate transport flowctl");
+      break;
+    // this is the same as no action b/c every time the transport enters the
+    // writing path it will maybe do an update
+    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
+      break;
+  }
+}
+
 static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                        double bdp_dbl) {
   // initial window size bounded [1,2^31-1], but we set the min to 128.
@@ -2157,9 +2268,10 @@
   if (delta == 0 || (delta > -bdp / 10 && delta < bdp / 10)) {
     return;
   }
-  if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
-    gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
-            (int)bdp);
+  if (GRPC_TRACER_ON(grpc_bdp_estimator_trace) ||
+      GRPC_TRACER_ON(grpc_flowctl_trace)) {
+    gpr_log(GPR_DEBUG, "%s | %p[%s] | update initial window size to %d",
+            t->peer_string, t, t->is_client ? "cli" : "svr", (int)bdp);
   }
   queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
                        (uint32_t)bdp);
@@ -2259,8 +2371,8 @@
     GPR_TIMER_END("reading_action.parse", 0);
 
     GPR_TIMER_BEGIN("post_parse_locked", 0);
-    if (t->initial_window_update != 0) {
-      if (t->initial_window_update > 0) {
+    if (t->flow_control.initial_window_update != 0) {
+      if (t->flow_control.initial_window_update > 0) {
         grpc_chttp2_stream *s;
         while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
           grpc_chttp2_become_writable(
@@ -2268,7 +2380,7 @@
               "unstalled");
         }
       }
-      t->initial_window_update = 0;
+      t->flow_control.initial_window_update = 0;
     }
     GPR_TIMER_END("post_parse_locked", 0);
   }
@@ -2542,54 +2654,6 @@
   }
 }
 
-static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
-                                                     grpc_chttp2_transport *t,
-                                                     grpc_chttp2_stream *s,
-                                                     size_t max_size_hint,
-                                                     size_t have_already) {
-  uint32_t max_recv_bytes;
-  uint32_t initial_window_size =
-      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-
-  /* clamp max recv hint to an allowable size */
-  if (max_size_hint >= UINT32_MAX - initial_window_size) {
-    max_recv_bytes = UINT32_MAX - initial_window_size;
-  } else {
-    max_recv_bytes = (uint32_t)max_size_hint;
-  }
-
-  /* account for bytes already received but unknown to higher layers */
-  if (max_recv_bytes >= have_already) {
-    max_recv_bytes -= (uint32_t)have_already;
-  } else {
-    max_recv_bytes = 0;
-  }
-
-  /* add some small lookahead to keep pipelines flowing */
-  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size);
-  if (s->incoming_window_delta < max_recv_bytes && !s->read_closed) {
-    uint32_t add_max_recv_bytes =
-        (uint32_t)(max_recv_bytes - s->incoming_window_delta);
-    grpc_chttp2_stream_write_type write_type =
-        GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED;
-    if (s->incoming_window_delta + initial_window_size <
-        (int64_t)have_already) {
-      write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
-    }
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s,
-                                                         add_max_recv_bytes);
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
-                                   add_max_recv_bytes);
-    if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -
-            (int64_t)s->announce_window >
-        (int64_t)initial_window_size / 2) {
-      write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
-    }
-    grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
-                                "read_incoming_stream");
-  }
-}
-
 static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
                                              void *argp,
                                              grpc_error *error_ignored) {
@@ -2598,13 +2662,20 @@
   grpc_chttp2_stream *s = bs->stream;
 
   size_t cur_length = s->frame_storage.length;
-  incoming_byte_stream_update_flow_control(
-      exec_ctx, t, s, bs->next_action.max_size_hint, cur_length);
-
+  if (!s->read_closed) {
+    grpc_chttp2_flowctl_incoming_bs_update(&t->flow_control, &s->flow_control,
+                                           bs->next_action.max_size_hint,
+                                           cur_length);
+    grpc_chttp2_act_on_flowctl_action(
+        exec_ctx,
+        grpc_chttp2_flowctl_get_action(&t->flow_control, &s->flow_control), t,
+        s);
+  }
   GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
   if (s->frame_storage.length > 0) {
     grpc_slice_buffer_swap(&s->frame_storage,
                            &s->unprocessed_incoming_frames_buffer);
+    s->unprocessed_incoming_frames_decompressed = false;
     GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE);
   } else if (s->byte_stream_error != GRPC_ERROR_NONE) {
     GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete,
@@ -2666,17 +2737,41 @@
   grpc_chttp2_incoming_byte_stream *bs =
       (grpc_chttp2_incoming_byte_stream *)byte_stream;
   grpc_chttp2_stream *s = bs->stream;
+  grpc_error *error;
 
   if (s->unprocessed_incoming_frames_buffer.length > 0) {
-    grpc_error *error = grpc_deframe_unprocessed_incoming_frames(
+    if (s->stream_compression_recv_enabled &&
+        !s->unprocessed_incoming_frames_decompressed) {
+      bool end_of_context;
+      if (!s->stream_decompression_ctx) {
+        s->stream_decompression_ctx = grpc_stream_compression_context_create(
+            GRPC_STREAM_COMPRESSION_DECOMPRESS);
+      }
+      if (!grpc_stream_decompress(s->stream_decompression_ctx,
+                                  &s->unprocessed_incoming_frames_buffer,
+                                  s->decompressed_data_buffer, NULL, MAX_SIZE_T,
+                                  &end_of_context)) {
+        error =
+            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
+        return error;
+      }
+      GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
+      grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
+                             s->decompressed_data_buffer);
+      s->unprocessed_incoming_frames_decompressed = true;
+      if (end_of_context) {
+        grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
+        s->stream_decompression_ctx = NULL;
+      }
+    }
+    error = grpc_deframe_unprocessed_incoming_frames(
         exec_ctx, &s->data_parser, s, &s->unprocessed_incoming_frames_buffer,
         slice, NULL);
     if (error != GRPC_ERROR_NONE) {
       return error;
     }
   } else {
-    grpc_error *error =
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
+    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
     GRPC_CLOSURE_SCHED(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error));
     return error;
   }
@@ -2684,22 +2779,9 @@
   return GRPC_ERROR_NONE;
 }
 
-static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
-                                         grpc_byte_stream *byte_stream);
-
 static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
                                                 void *byte_stream,
-                                                grpc_error *error_ignored) {
-  grpc_chttp2_incoming_byte_stream *bs = byte_stream;
-  grpc_chttp2_stream *s = bs->stream;
-  grpc_chttp2_transport *t = s->t;
-
-  GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy);
-  incoming_byte_stream_unref(exec_ctx, bs);
-  s->pending_byte_stream = false;
-  grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
-  grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
-}
+                                                grpc_error *error_ignored);
 
 static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
                                          grpc_byte_stream *byte_stream) {
@@ -2766,6 +2848,33 @@
   return error;
 }
 
+static void incoming_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                                          grpc_byte_stream *byte_stream,
+                                          grpc_error *error) {
+  grpc_chttp2_incoming_byte_stream *bs =
+      (grpc_chttp2_incoming_byte_stream *)byte_stream;
+  GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
+      exec_ctx, bs, error, true /* reset_on_error */));
+}
+
+static const grpc_byte_stream_vtable grpc_chttp2_incoming_byte_stream_vtable = {
+    incoming_byte_stream_next, incoming_byte_stream_pull,
+    incoming_byte_stream_shutdown, incoming_byte_stream_destroy};
+
+static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
+                                                void *byte_stream,
+                                                grpc_error *error_ignored) {
+  grpc_chttp2_incoming_byte_stream *bs = byte_stream;
+  grpc_chttp2_stream *s = bs->stream;
+  grpc_chttp2_transport *t = s->t;
+
+  GPR_ASSERT(bs->base.vtable == &grpc_chttp2_incoming_byte_stream_vtable);
+  incoming_byte_stream_unref(exec_ctx, bs);
+  s->pending_byte_stream = false;
+  grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
+  grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
+}
+
 grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
     uint32_t frame_size, uint32_t flags) {
@@ -2774,9 +2883,7 @@
   incoming_byte_stream->base.length = frame_size;
   incoming_byte_stream->remaining_bytes = frame_size;
   incoming_byte_stream->base.flags = flags;
-  incoming_byte_stream->base.next = incoming_byte_stream_next;
-  incoming_byte_stream->base.pull = incoming_byte_stream_pull;
-  incoming_byte_stream->base.destroy = incoming_byte_stream_destroy;
+  incoming_byte_stream->base.vtable = &grpc_chttp2_incoming_byte_stream_vtable;
   gpr_ref_init(&incoming_byte_stream->refs, 2);
   incoming_byte_stream->transport = t;
   incoming_byte_stream->stream = s;
@@ -2873,83 +2980,6 @@
 }
 
 /*******************************************************************************
- * TRACING
- */
-
-static char *format_flowctl_context_var(const char *context, const char *var,
-                                        int64_t val, uint32_t id) {
-  char *name;
-  if (context == NULL) {
-    name = gpr_strdup(var);
-  } else if (0 == strcmp(context, "t")) {
-    GPR_ASSERT(id == 0);
-    gpr_asprintf(&name, "TRANSPORT:%s", var);
-  } else if (0 == strcmp(context, "s")) {
-    GPR_ASSERT(id != 0);
-    gpr_asprintf(&name, "STREAM[%d]:%s", id, var);
-  } else {
-    gpr_asprintf(&name, "BAD_CONTEXT[%s][%d]:%s", context, id, var);
-  }
-  char *name_fld = gpr_leftpad(name, ' ', 64);
-  char *value;
-  gpr_asprintf(&value, "%" PRId64, val);
-  char *value_fld = gpr_leftpad(value, ' ', 8);
-  char *result;
-  gpr_asprintf(&result, "%s %s", name_fld, value_fld);
-  gpr_free(name);
-  gpr_free(name_fld);
-  gpr_free(value);
-  gpr_free(value_fld);
-  return result;
-}
-
-void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
-                               grpc_chttp2_flowctl_op op, const char *context1,
-                               const char *var1, const char *context2,
-                               const char *var2, int is_client,
-                               uint32_t stream_id, int64_t val1, int64_t val2) {
-  char *tmp_phase;
-  char *label1 = format_flowctl_context_var(context1, var1, val1, stream_id);
-  char *label2 = format_flowctl_context_var(context2, var2, val2, stream_id);
-  char *clisvr = is_client ? "client" : "server";
-  char *prefix;
-
-  tmp_phase = gpr_leftpad(phase, ' ', 8);
-  gpr_asprintf(&prefix, "FLOW %s: %s ", tmp_phase, clisvr);
-  gpr_free(tmp_phase);
-
-  switch (op) {
-    case GRPC_CHTTP2_FLOWCTL_MOVE:
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sMOVE   %s <- %s giving %" PRId64, prefix, label1, label2,
-                val1 + val2);
-      }
-      break;
-    case GRPC_CHTTP2_FLOWCTL_CREDIT:
-      GPR_ASSERT(val2 >= 0);
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sCREDIT %s by %s giving %" PRId64, prefix, label1, label2,
-                val1 + val2);
-      }
-      break;
-    case GRPC_CHTTP2_FLOWCTL_DEBIT:
-      GPR_ASSERT(val2 >= 0);
-      if (val2 != 0) {
-        gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-                "%sDEBIT  %s by %s giving %" PRId64, prefix, label1, label2,
-                val1 - val2);
-      }
-      break;
-  }
-
-  gpr_free(label1);
-  gpr_free(label2);
-  gpr_free(prefix);
-}
-
-/*******************************************************************************
  * INTEGRATION GLUE
  */
 
diff --git a/src/core/ext/transport/chttp2/transport/flow_control.c b/src/core/ext/transport/chttp2/transport/flow_control.c
new file mode 100644
index 0000000..c9f7eab
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/flow_control.c
@@ -0,0 +1,369 @@
+/*
+ *
+ * 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 "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/support/string.h"
+
+static uint32_t grpc_chttp2_target_announced_window(
+    const grpc_chttp2_transport_flowctl* tfc);
+
+#ifndef NDEBUG
+
+typedef struct {
+  int64_t remote_window;
+  int64_t target_window;
+  int64_t announced_window;
+  int64_t remote_window_delta;
+  int64_t local_window_delta;
+  int64_t announced_window_delta;
+} shadow_flow_control;
+
+static void pretrace(shadow_flow_control* shadow_fc,
+                     grpc_chttp2_transport_flowctl* tfc,
+                     grpc_chttp2_stream_flowctl* sfc) {
+  shadow_fc->remote_window = tfc->remote_window;
+  shadow_fc->target_window = grpc_chttp2_target_announced_window(tfc);
+  shadow_fc->announced_window = tfc->announced_window;
+  if (sfc != NULL) {
+    shadow_fc->remote_window_delta = sfc->remote_window_delta;
+    shadow_fc->local_window_delta = sfc->local_window_delta;
+    shadow_fc->announced_window_delta = sfc->announced_window_delta;
+  }
+}
+
+static char* fmt_str(int64_t old, int64_t new) {
+  char* str;
+  if (old != new) {
+    gpr_asprintf(&str, "%" PRId64 " -> %" PRId64 "", old, new);
+  } else {
+    gpr_asprintf(&str, "%" PRId64 "", old);
+  }
+  char* str_lp = gpr_leftpad(str, ' ', 30);
+  gpr_free(str);
+  return str_lp;
+}
+
+static void posttrace(shadow_flow_control* shadow_fc,
+                      grpc_chttp2_transport_flowctl* tfc,
+                      grpc_chttp2_stream_flowctl* sfc, char* reason) {
+  uint32_t acked_local_window =
+      tfc->t->settings[GRPC_SENT_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  uint32_t remote_window =
+      tfc->t->settings[GRPC_PEER_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  char* trw_str = fmt_str(shadow_fc->remote_window, tfc->remote_window);
+  char* tlw_str = fmt_str(shadow_fc->target_window,
+                          grpc_chttp2_target_announced_window(tfc));
+  char* taw_str = fmt_str(shadow_fc->announced_window, tfc->announced_window);
+  char* srw_str;
+  char* slw_str;
+  char* saw_str;
+  if (sfc != NULL) {
+    srw_str = fmt_str(shadow_fc->remote_window_delta + remote_window,
+                      sfc->remote_window_delta + remote_window);
+    slw_str = fmt_str(shadow_fc->local_window_delta + acked_local_window,
+                      sfc->local_window_delta + acked_local_window);
+    saw_str = fmt_str(shadow_fc->announced_window_delta + acked_local_window,
+                      sfc->announced_window_delta + acked_local_window);
+  } else {
+    srw_str = gpr_leftpad("", ' ', 30);
+    slw_str = gpr_leftpad("", ' ', 30);
+    saw_str = gpr_leftpad("", ' ', 30);
+  }
+  gpr_log(GPR_DEBUG,
+          "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s",
+          tfc, sfc != NULL ? sfc->s->id : 0, tfc->t->is_client ? "cli" : "svr",
+          reason, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str);
+  gpr_free(trw_str);
+  gpr_free(tlw_str);
+  gpr_free(taw_str);
+  gpr_free(srw_str);
+  gpr_free(slw_str);
+  gpr_free(saw_str);
+}
+
+static char* urgency_to_string(grpc_chttp2_flowctl_urgency urgency) {
+  switch (urgency) {
+    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
+      return "no action";
+    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
+      return "update immediately";
+    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
+      return "queue update";
+    default:
+      GPR_UNREACHABLE_CODE(return "unknown");
+  }
+  GPR_UNREACHABLE_CODE(return "unknown");
+}
+
+static void trace_action(grpc_chttp2_flowctl_action action) {
+  gpr_log(GPR_DEBUG, "transport: %s,  stream: %s",
+          urgency_to_string(action.send_transport_update),
+          urgency_to_string(action.send_stream_update));
+}
+
+#define PRETRACE(tfc, sfc)       \
+  shadow_flow_control shadow_fc; \
+  GRPC_FLOW_CONTROL_IF_TRACING(pretrace(&shadow_fc, tfc, sfc))
+#define POSTTRACE(tfc, sfc, reason) \
+  GRPC_FLOW_CONTROL_IF_TRACING(posttrace(&shadow_fc, tfc, sfc, reason))
+#define TRACEACTION(action) GRPC_FLOW_CONTROL_IF_TRACING(trace_action(action))
+#else
+#define PRETRACE(tfc, sfc)
+#define POSTTRACE(tfc, sfc, reason)
+#define TRACEACTION(action)
+#endif
+
+/* How many bytes of incoming flow control would we like to advertise */
+static uint32_t grpc_chttp2_target_announced_window(
+    const grpc_chttp2_transport_flowctl* tfc) {
+  return (uint32_t)GPR_MIN(
+      (int64_t)((1u << 31) - 1),
+      tfc->announced_stream_total_over_incoming_window +
+          tfc->t->settings[GRPC_SENT_SETTINGS]
+                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
+}
+
+// we have sent data on the wire, we must track this in our bookkeeping for the
+// remote peer's flow control.
+void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport_flowctl* tfc,
+                                   grpc_chttp2_stream_flowctl* sfc,
+                                   int64_t size) {
+  PRETRACE(tfc, sfc);
+  tfc->remote_window -= size;
+  sfc->remote_window_delta -= size;
+  POSTTRACE(tfc, sfc, "  data sent");
+}
+
+static void announced_window_delta_preupdate(grpc_chttp2_transport_flowctl* tfc,
+                                             grpc_chttp2_stream_flowctl* sfc) {
+  if (sfc->announced_window_delta > 0) {
+    tfc->announced_stream_total_over_incoming_window -=
+        sfc->announced_window_delta;
+  } else {
+    tfc->announced_stream_total_under_incoming_window +=
+        -sfc->announced_window_delta;
+  }
+}
+
+static void announced_window_delta_postupdate(
+    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
+  if (sfc->announced_window_delta > 0) {
+    tfc->announced_stream_total_over_incoming_window +=
+        sfc->announced_window_delta;
+  } else {
+    tfc->announced_stream_total_under_incoming_window -=
+        -sfc->announced_window_delta;
+  }
+}
+
+// We have received data from the wire. We must track this in our own flow
+// control bookkeeping.
+// Returns an error if the incoming frame violates our flow control.
+grpc_error* grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport_flowctl* tfc,
+                                          grpc_chttp2_stream_flowctl* sfc,
+                                          int64_t incoming_frame_size) {
+  uint32_t sent_init_window =
+      tfc->t->settings[GRPC_SENT_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  uint32_t acked_init_window =
+      tfc->t->settings[GRPC_ACKED_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  PRETRACE(tfc, sfc);
+  if (incoming_frame_size > tfc->announced_window) {
+    char* msg;
+    gpr_asprintf(&msg,
+                 "frame of size %" PRId64 " overflows local window of %" PRId64,
+                 incoming_frame_size, tfc->announced_window);
+    grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+    gpr_free(msg);
+    return err;
+  }
+
+  if (sfc != NULL) {
+    int64_t acked_stream_window =
+        sfc->announced_window_delta + acked_init_window;
+    int64_t sent_stream_window = sfc->announced_window_delta + sent_init_window;
+    if (incoming_frame_size > acked_stream_window) {
+      if (incoming_frame_size <= sent_stream_window) {
+        gpr_log(
+            GPR_ERROR,
+            "Incoming frame of size %" PRId64
+            " exceeds local window size of %" PRId64
+            ".\n"
+            "The (un-acked, future) window size would be %" PRId64
+            " which is not exceeded.\n"
+            "This would usually cause a disconnection, but allowing it due to"
+            "broken HTTP2 implementations in the wild.\n"
+            "See (for example) https://github.com/netty/netty/issues/6520.",
+            incoming_frame_size, acked_stream_window, sent_stream_window);
+      } else {
+        char* msg;
+        gpr_asprintf(&msg, "frame of size %" PRId64
+                           " overflows local window of %" PRId64,
+                     incoming_frame_size, acked_stream_window);
+        grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+        gpr_free(msg);
+        return err;
+      }
+    }
+
+    announced_window_delta_preupdate(tfc, sfc);
+    sfc->announced_window_delta -= incoming_frame_size;
+    announced_window_delta_postupdate(tfc, sfc);
+    sfc->local_window_delta -= incoming_frame_size;
+  }
+
+  tfc->announced_window -= incoming_frame_size;
+
+  POSTTRACE(tfc, sfc, "  data recv");
+  return GRPC_ERROR_NONE;
+}
+
+// Returns a non zero announce integer if we should send a transport window
+// update
+uint32_t grpc_chttp2_flowctl_maybe_send_transport_update(
+    grpc_chttp2_transport_flowctl* tfc) {
+  PRETRACE(tfc, NULL);
+  uint32_t target_announced_window = grpc_chttp2_target_announced_window(tfc);
+  uint32_t threshold_to_send_transport_window_update =
+      tfc->t->outbuf.count > 0 ? 3 * target_announced_window / 4
+                               : target_announced_window / 2;
+  if (tfc->announced_window <= threshold_to_send_transport_window_update &&
+      tfc->announced_window != target_announced_window) {
+    uint32_t announce = (uint32_t)GPR_CLAMP(
+        target_announced_window - tfc->announced_window, 0, UINT32_MAX);
+    tfc->announced_window += announce;
+    POSTTRACE(tfc, NULL, "t updt sent");
+    return announce;
+  }
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      gpr_log(GPR_DEBUG, "%p[0][%s] will not send transport update", tfc,
+              tfc->t->is_client ? "cli" : "svr"));
+  return 0;
+}
+
+// Returns a non zero announce integer if we should send a stream window update
+uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(
+    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
+  PRETRACE(tfc, sfc);
+  if (sfc->local_window_delta > sfc->announced_window_delta) {
+    uint32_t announce = (uint32_t)GPR_CLAMP(
+        sfc->local_window_delta - sfc->announced_window_delta, 0, UINT32_MAX);
+    announced_window_delta_preupdate(tfc, sfc);
+    sfc->announced_window_delta += announce;
+    announced_window_delta_postupdate(tfc, sfc);
+    POSTTRACE(tfc, sfc, "s updt sent");
+    return announce;
+  }
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      gpr_log(GPR_DEBUG, "%p[%u][%s] will not send stream update", tfc,
+              sfc->s->id, tfc->t->is_client ? "cli" : "svr"));
+  return 0;
+}
+
+// we have received a WINDOW_UPDATE frame for a transport
+void grpc_chttp2_flowctl_recv_transport_update(
+    grpc_chttp2_transport_flowctl* tfc, uint32_t size) {
+  PRETRACE(tfc, NULL);
+  tfc->remote_window += size;
+  POSTTRACE(tfc, NULL, "t updt recv");
+}
+
+// we have received a WINDOW_UPDATE frame for a stream
+void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_transport_flowctl* tfc,
+                                            grpc_chttp2_stream_flowctl* sfc,
+                                            uint32_t size) {
+  PRETRACE(tfc, sfc);
+  sfc->remote_window_delta += size;
+  POSTTRACE(tfc, sfc, "s updt recv");
+}
+
+void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport_flowctl* tfc,
+                                            grpc_chttp2_stream_flowctl* sfc,
+                                            size_t max_size_hint,
+                                            size_t have_already) {
+  PRETRACE(tfc, sfc);
+  uint32_t max_recv_bytes;
+  uint32_t sent_init_window =
+      tfc->t->settings[GRPC_SENT_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+
+  /* clamp max recv hint to an allowable size */
+  if (max_size_hint >= UINT32_MAX - sent_init_window) {
+    max_recv_bytes = UINT32_MAX - sent_init_window;
+  } else {
+    max_recv_bytes = (uint32_t)max_size_hint;
+  }
+
+  /* account for bytes already received but unknown to higher layers */
+  if (max_recv_bytes >= have_already) {
+    max_recv_bytes -= (uint32_t)have_already;
+  } else {
+    max_recv_bytes = 0;
+  }
+
+  /* add some small lookahead to keep pipelines flowing */
+  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - sent_init_window);
+  if (sfc->local_window_delta < max_recv_bytes) {
+    uint32_t add_max_recv_bytes =
+        (uint32_t)(max_recv_bytes - sfc->local_window_delta);
+    sfc->local_window_delta += add_max_recv_bytes;
+  }
+  POSTTRACE(tfc, sfc, "app st recv");
+}
+
+void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_transport_flowctl* tfc,
+                                        grpc_chttp2_stream_flowctl* sfc) {
+  announced_window_delta_preupdate(tfc, sfc);
+}
+
+grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_action(
+    const grpc_chttp2_transport_flowctl* tfc,
+    const grpc_chttp2_stream_flowctl* sfc) {
+  grpc_chttp2_flowctl_action action;
+  memset(&action, 0, sizeof(action));
+  uint32_t target_announced_window = grpc_chttp2_target_announced_window(tfc);
+  if (tfc->announced_window < target_announced_window / 2) {
+    action.send_transport_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
+  }
+  if (sfc != NULL && !sfc->s->read_closed) {
+    uint32_t sent_init_window =
+        tfc->t->settings[GRPC_SENT_SETTINGS]
+                        [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    if ((int64_t)sfc->local_window_delta >
+            (int64_t)sfc->announced_window_delta &&
+        (int64_t)sfc->announced_window_delta + sent_init_window <=
+            sent_init_window / 2) {
+      action.send_stream_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
+    } else if (sfc->local_window_delta > sfc->announced_window_delta) {
+      action.send_stream_update = GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE;
+    }
+  }
+  TRACEACTION(action);
+  return action;
+}
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c
index dead6be..222d217 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.c
+++ b/src/core/ext/transport/chttp2/transport/frame_data.c
@@ -293,7 +293,6 @@
                                           grpc_chttp2_transport *t,
                                           grpc_chttp2_stream *s,
                                           grpc_slice slice, int is_last) {
-  /* grpc_error *error = parse_inner_buffer(exec_ctx, p, t, s, slice); */
   if (!s->pending_byte_stream) {
     grpc_slice_ref_internal(slice);
     grpc_slice_buffer_add(&s->frame_storage, slice);
@@ -304,6 +303,7 @@
     grpc_slice_buffer_add(&s->unprocessed_incoming_frames_buffer, slice);
     GRPC_CLOSURE_SCHED(exec_ctx, s->on_next, GRPC_ERROR_NONE);
     s->on_next = NULL;
+    s->unprocessed_incoming_frames_decompressed = false;
   } else {
     grpc_slice_ref_internal(slice);
     grpc_slice_buffer_add(&s->frame_storage, slice);
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
index e3e432a..057d3d9 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.c
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -201,11 +201,13 @@
           }
           if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
               parser->incoming_settings[id] != parser->value) {
-            t->initial_window_update +=
+            t->flow_control.initial_window_update +=
                 (int64_t)parser->value - parser->incoming_settings[id];
-            if (GRPC_TRACER_ON(grpc_http_trace)) {
-              gpr_log(GPR_DEBUG, "adding %d for initial_window change",
-                      (int)t->initial_window_update);
+            if (GRPC_TRACER_ON(grpc_http_trace) ||
+                GRPC_TRACER_ON(grpc_flowctl_trace)) {
+              gpr_log(GPR_DEBUG, "%p[%s] adding %d for initial_window change",
+                      t, t->is_client ? "cli" : "svr",
+                      (int)t->flow_control.initial_window_update);
             }
           }
           parser->incoming_settings[id] = parser->value;
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c
index 682be2c..65f3b01 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.c
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c
@@ -95,8 +95,8 @@
 
     if (t->incoming_stream_id != 0) {
       if (s != NULL) {
-        GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window_delta,
-                                       received_update);
+        grpc_chttp2_flowctl_recv_stream_update(
+            &t->flow_control, &s->flow_control, received_update);
         if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
           grpc_chttp2_become_writable(
               exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
@@ -104,10 +104,10 @@
         }
       }
     } else {
-      bool was_zero = t->outgoing_window <= 0;
-      GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parse", t, outgoing_window,
-                                        received_update);
-      bool is_zero = t->outgoing_window <= 0;
+      bool was_zero = t->flow_control.remote_window <= 0;
+      grpc_chttp2_flowctl_recv_transport_update(&t->flow_control,
+                                                received_update);
+      bool is_zero = t->flow_control.remote_window <= 0;
       if (was_zero && !is_zero) {
         grpc_chttp2_initiate_write(exec_ctx, t, "new_global_flow_control");
       }
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index a5b67e5..f26f14d 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -33,6 +33,7 @@
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
 #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
 #include "src/core/ext/transport/chttp2/transport/stream_map.h"
+#include "src/core/lib/compression/stream_compression.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/timer.h"
@@ -212,6 +213,35 @@
   GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED,
 } grpc_chttp2_keepalive_state;
 
+typedef struct {
+  /** initial window change. This is tracked as we parse settings frames from
+   * the remote peer. If there is a positive delta, then we will make all
+   * streams readable since they may have become unstalled */
+  int64_t initial_window_update;
+
+  /** Our bookkeeping for the remote peer's available window */
+  int64_t remote_window;
+
+  /** calculating what we should give for local window:
+      we track the total amount of flow control over initial window size
+      across all streams: this is data that we want to receive right now (it
+      has an outstanding read)
+      and the total amount of flow control under initial window size across all
+      streams: this is data we've read early
+      we want to adjust incoming_window such that:
+      incoming_window = total_over - max(bdp - total_under, 0) */
+  int64_t announced_stream_total_over_incoming_window;
+  int64_t announced_stream_total_under_incoming_window;
+
+  /** This is out window according to what we have sent to our remote peer. The
+   * difference between this and target window is what we use to decide when
+   * to send WINDOW_UPDATE frames. */
+  int64_t announced_window;
+
+  // read only pointer back to transport for certain data
+  const grpc_chttp2_transport *t;
+} grpc_chttp2_transport_flowctl;
+
 struct grpc_chttp2_transport {
   grpc_transport base; /* must be first */
   gpr_refcount refs;
@@ -270,7 +300,6 @@
   grpc_slice_buffer outbuf;
   /** hpack encoding */
   grpc_chttp2_hpack_compressor hpack_compressor;
-  int64_t outgoing_window;
   /** is this a client? */
   uint8_t is_client;
 
@@ -327,21 +356,14 @@
   /** parser for goaway frames */
   grpc_chttp2_goaway_parser goaway_parser;
 
-  /** initial window change */
-  int64_t initial_window_update;
+  grpc_chttp2_transport_flowctl flow_control;
 
-  /** window available for peer to send to us */
-  int64_t incoming_window;
-  /** calculating what we should give for incoming window:
-      we track the total amount of flow control over initial window size
-      across all streams: this is data that we want to receive right now (it
-      has an outstanding read)
-      and the total amount of flow control under initial window size across all
-      streams: this is data we've read early
-      we want to adjust incoming_window such that:
-      incoming_window = total_over - max(bdp - total_under, 0) */
-  int64_t stream_total_over_incoming_window;
-  int64_t stream_total_under_incoming_window;
+  /* bdp estimation */
+  grpc_bdp_estimator bdp_estimator;
+
+  /* pid controller */
+  grpc_pid_controller pid_controller;
+  gpr_timespec last_pid_update;
 
   /* deframing */
   grpc_chttp2_deframe_transport_state deframe_state;
@@ -368,11 +390,8 @@
   grpc_chttp2_write_cb *write_cb_pool;
 
   /* bdp estimator */
-  grpc_bdp_estimator bdp_estimator;
-  grpc_pid_controller pid_controller;
   grpc_closure start_bdp_ping_locked;
   grpc_closure finish_bdp_ping_locked;
-  gpr_timespec last_pid_update;
 
   /* if non-NULL, close the transport with this error when writes are finished
    */
@@ -421,6 +440,25 @@
   GPRC_METADATA_PUBLISHED_AT_CLOSE
 } grpc_published_metadata_method;
 
+typedef struct {
+  /** window available for us to send to peer, over or under the initial window
+   * size of the transport... ie:
+   * remote_window = remote_window_delta + transport.initial_window_size */
+  int64_t remote_window_delta;
+
+  /** window available for peer to send to us (as a delta on
+   * transport.initial_window_size)
+   * local_window = local_window_delta + transport.initial_window_size */
+  int64_t local_window_delta;
+
+  /** window available for peer to send to us over this stream that we have
+   * announced to the peer */
+  int64_t announced_window_delta;
+
+  // read only pointer back to stream for data
+  const grpc_chttp2_stream *s;
+} grpc_chttp2_stream_flowctl;
+
 struct grpc_chttp2_stream {
   grpc_chttp2_transport *t;
   grpc_stream_refcount *refcount;
@@ -434,10 +472,6 @@
   /** HTTP2 stream id for this stream, or zero if one has not been assigned */
   uint32_t id;
 
-  /** window available for us to send to peer, over or under the initial window
-   * size of the transport... ie:
-   * outgoing_window = outgoing_window_delta + transport.initial_window_size */
-  int64_t outgoing_window_delta;
   /** things the upper layers would like to send */
   grpc_metadata_batch *send_initial_metadata;
   grpc_closure *send_initial_metadata_finished;
@@ -504,10 +538,6 @@
   grpc_error *forced_close_error;
   /** how many header frames have we received? */
   uint8_t header_frames_received;
-  /** window available for peer to send to us (as a delta on
-   * transport.initial_window_size)
-   * incoming_window = incoming_window_delta + transport.initial_window_size */
-  int64_t incoming_window_delta;
   /** parsing state for data frames */
   /* Accessed only by transport thread when stream->pending_byte_stream == false
    * Accessed only by application thread when stream->pending_byte_stream ==
@@ -518,13 +548,34 @@
 
   bool sent_initial_metadata;
   bool sent_trailing_metadata;
-  /** how much window should we announce? */
-  uint32_t announce_window;
+
+  grpc_chttp2_stream_flowctl flow_control;
+
   grpc_slice_buffer flow_controlled_buffer;
 
   grpc_chttp2_write_cb *on_write_finished_cbs;
   grpc_chttp2_write_cb *finish_after_write;
   size_t sending_bytes;
+
+  /** Whether stream compression send is enabled */
+  bool stream_compression_recv_enabled;
+  /** Whether stream compression recv is enabled */
+  bool stream_compression_send_enabled;
+  /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
+   */
+  bool unprocessed_incoming_frames_decompressed;
+  /** Stream compression decompress context */
+  grpc_stream_compression_context *stream_decompression_ctx;
+  /** Stream compression compress context */
+  grpc_stream_compression_context *stream_compression_ctx;
+
+  /** Buffer storing data that is compressed but not sent */
+  grpc_slice_buffer *compressed_data_buffer;
+  /** Amount of uncompressed bytes sent out when compressed_data_buffer is
+   * emptied */
+  size_t uncompressed_data_size;
+  /** Temporary buffer storing decompressed data */
+  grpc_slice_buffer *decompressed_data_buffer;
 };
 
 /** Transport writing call flow:
@@ -600,6 +651,75 @@
 bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
                                                grpc_chttp2_stream *s);
 
+/********* Flow Control ***************/
+
+// we have sent data on the wire
+void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport_flowctl *tfc,
+                                   grpc_chttp2_stream_flowctl *sfc,
+                                   int64_t size);
+
+// we have received data from the wire
+grpc_error *grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport_flowctl *tfc,
+                                          grpc_chttp2_stream_flowctl *sfc,
+                                          int64_t incoming_frame_size);
+
+// returns an announce if we should send a transport update to our peer,
+// else returns zero
+uint32_t grpc_chttp2_flowctl_maybe_send_transport_update(
+    grpc_chttp2_transport_flowctl *tfc);
+
+// returns an announce if we should send a stream update to our peer, else
+// returns zero
+uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(
+    grpc_chttp2_transport_flowctl *tfc, grpc_chttp2_stream_flowctl *sfc);
+
+// we have received a WINDOW_UPDATE frame for a transport
+void grpc_chttp2_flowctl_recv_transport_update(
+    grpc_chttp2_transport_flowctl *tfc, uint32_t size);
+
+// we have received a WINDOW_UPDATE frame for a stream
+void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_transport_flowctl *tfc,
+                                            grpc_chttp2_stream_flowctl *sfc,
+                                            uint32_t size);
+
+// the application is asking for a certain amount of bytes
+void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport_flowctl *tfc,
+                                            grpc_chttp2_stream_flowctl *sfc,
+                                            size_t max_size_hint,
+                                            size_t have_already);
+
+void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_transport_flowctl *tfc,
+                                        grpc_chttp2_stream_flowctl *sfc);
+
+typedef enum {
+  // Nothing to be done.
+  GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED = 0,
+  // Initiate a write to update the initial window immediately.
+  GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY,
+  // Push the flow control update into a send buffer, to be sent
+  // out the next time a write is initiated.
+  GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE,
+} grpc_chttp2_flowctl_urgency;
+
+typedef struct {
+  grpc_chttp2_flowctl_urgency send_stream_update;
+  grpc_chttp2_flowctl_urgency send_transport_update;
+} grpc_chttp2_flowctl_action;
+
+// Reads the flow control data and returns and actionable struct that will tell
+// chttp2 exactly what it needs to do
+grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_action(
+    const grpc_chttp2_transport_flowctl *tfc,
+    const grpc_chttp2_stream_flowctl *sfc);
+
+// Takes in a flow control action and performs all the needed operations.
+void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_flowctl_action action,
+                                       grpc_chttp2_transport *t,
+                                       grpc_chttp2_stream *s);
+
+/********* End of Flow Control ***************/
+
 grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
                                                       uint32_t id);
 grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
@@ -620,6 +740,9 @@
                                        grpc_closure **pclosure,
                                        grpc_error *error, const char *desc);
 
+#define GRPC_HEADER_SIZE_IN_BYTES 5
+#define MAX_SIZE_T (~(size_t)0)
+
 #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
 #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
   (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
@@ -627,126 +750,22 @@
 extern grpc_tracer_flag grpc_http_trace;
 extern grpc_tracer_flag grpc_flowctl_trace;
 
+#ifndef NDEBUG
+#define GRPC_FLOW_CONTROL_IF_TRACING(stmt)   \
+  if (!(GRPC_TRACER_ON(grpc_flowctl_trace))) \
+    ;                                        \
+  else                                       \
+  stmt
+#else
+#define GRPC_FLOW_CONTROL_IF_TRACING(stmt)
+#endif
+
 #define GRPC_CHTTP2_IF_TRACING(stmt)      \
   if (!(GRPC_TRACER_ON(grpc_http_trace))) \
     ;                                     \
   else                                    \
   stmt
 
-typedef enum {
-  GRPC_CHTTP2_FLOWCTL_MOVE,
-  GRPC_CHTTP2_FLOWCTL_CREDIT,
-  GRPC_CHTTP2_FLOWCTL_DEBIT
-} grpc_chttp2_flowctl_op;
-
-#define GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, id1, id2, dst_context, \
-                                     dst_var, src_context, src_var)           \
-  do {                                                                        \
-    assert(id1 == id2);                                                       \
-    if (GRPC_TRACER_ON(grpc_flowctl_trace)) {                                 \
-      grpc_chttp2_flowctl_trace(                                              \
-          __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context,  \
-          #dst_var, #src_context, #src_var, transport->is_client, id1,        \
-          dst_context->dst_var, src_context->src_var);                        \
-    }                                                                         \
-    dst_context->dst_var += src_context->src_var;                             \
-    src_context->src_var = 0;                                                 \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_MOVE_STREAM(phase, transport, dst_context, dst_var, \
-                                     src_context, src_var)                   \
-  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, dst_context->id,            \
-                               src_context->id, dst_context, dst_var,        \
-                               src_context, src_var)
-#define GRPC_CHTTP2_FLOW_MOVE_TRANSPORT(phase, dst_context, dst_var,           \
-                                        src_context, src_var)                  \
-  GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, dst_context, 0, 0, dst_context, dst_var, \
-                               src_context, src_var)
-
-#define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context,      \
-                                       dst_var, amount)                        \
-  do {                                                                         \
-    if (GRPC_TRACER_ON(grpc_flowctl_trace)) {                                  \
-      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
-                                GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context,      \
-                                #dst_var, NULL, #amount, transport->is_client, \
-                                id, dst_context->dst_var, amount);             \
-    }                                                                          \
-    dst_context->dst_var += amount;                                            \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, dst_var, \
-                                       amount)                                 \
-  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, dst_context->id,            \
-                                 dst_context, dst_var, amount)
-#define GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT(phase, dst_context, dst_var, amount) \
-  GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
-                                 amount)
-
-#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \
-    phase, transport, dst_context)                               \
-  if (dst_context->incoming_window_delta < 0) {                  \
-    transport->stream_total_under_incoming_window +=             \
-        dst_context->incoming_window_delta;                      \
-  } else if (dst_context->incoming_window_delta > 0) {           \
-    transport->stream_total_over_incoming_window -=              \
-        dst_context->incoming_window_delta;                      \
-  }
-
-#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \
-    phase, transport, dst_context)                                \
-  if (dst_context->incoming_window_delta < 0) {                   \
-    transport->stream_total_under_incoming_window -=              \
-        dst_context->incoming_window_delta;                       \
-  } else if (dst_context->incoming_window_delta > 0) {            \
-    transport->stream_total_over_incoming_window +=               \
-        dst_context->incoming_window_delta;                       \
-  }
-
-#define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(                 \
-    phase, transport, dst_context, amount)                                   \
-  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport,  \
-                                                          dst_context);      \
-  GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context,               \
-                                incoming_window_delta, amount);              \
-  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
-                                                           dst_context);
-
-#define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(                \
-    phase, transport, dst_context, amount)                                   \
-  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport,  \
-                                                          dst_context);      \
-  GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context,              \
-                                 incoming_window_delta, amount);             \
-  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
-                                                           dst_context);
-
-#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context,       \
-                                      dst_var, amount)                         \
-  do {                                                                         \
-    if (GRPC_TRACER_ON(grpc_flowctl_trace)) {                                  \
-      grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase,                     \
-                                GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context,       \
-                                #dst_var, NULL, #amount, transport->is_client, \
-                                id, dst_context->dst_var, amount);             \
-    }                                                                          \
-    dst_context->dst_var -= amount;                                            \
-  } while (0)
-
-#define GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, dst_var, \
-                                      amount)                                 \
-  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, dst_context->id,            \
-                                dst_context, dst_var, amount)
-#define GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT(phase, dst_context, dst_var, amount) \
-  GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
-                                amount)
-
-void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
-                               grpc_chttp2_flowctl_op op, const char *context1,
-                               const char *var1, const char *context2,
-                               const char *var2, int is_client,
-                               uint32_t stream_id, int64_t val1, int64_t val2);
-
 void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                              grpc_chttp2_stream *stream, grpc_error *error);
 void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
@@ -848,8 +867,6 @@
                                      grpc_chttp2_transport *t,
                                      grpc_chttp2_stream *s, grpc_error *error);
 
-uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t);
-
 /** Set the default keepalive configurations, must only be called at
     initialization */
 void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 3c8b470..18d163e 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -349,93 +349,25 @@
                          t->parser == grpc_chttp2_header_parser_parse);
 }
 
-static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
-                                          grpc_chttp2_transport *t,
-                                          grpc_chttp2_stream *s) {
-  uint32_t incoming_frame_size = t->incoming_frame_size;
-  if (incoming_frame_size > t->incoming_window) {
-    char *msg;
-    gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
-                 t->incoming_frame_size, t->incoming_window);
-    grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
-    gpr_free(msg);
-    return err;
-  }
-
-  if (s != NULL) {
-    if (incoming_frame_size >
-        s->incoming_window_delta +
-            t->settings[GRPC_ACKED_SETTINGS]
-                       [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
-      if (incoming_frame_size <=
-          s->incoming_window_delta +
-              t->settings[GRPC_SENT_SETTINGS]
-                         [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
-        gpr_log(
-            GPR_ERROR,
-            "Incoming frame of size %d exceeds incoming window size of %" PRId64
-            ".\n"
-            "The (un-acked, future) window size would be %" PRId64
-            " which is not exceeded.\n"
-            "This would usually cause a disconnection, but allowing it due to "
-            "broken HTTP2 implementations in the wild.\n"
-            "See (for example) https://github.com/netty/netty/issues/6520.",
-            t->incoming_frame_size,
-            s->incoming_window_delta +
-                t->settings[GRPC_ACKED_SETTINGS]
-                           [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
-            s->incoming_window_delta +
-                t->settings[GRPC_SENT_SETTINGS]
-                           [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
-      } else {
-        char *msg;
-        gpr_asprintf(&msg,
-                     "frame of size %d overflows incoming window of %" PRId64,
-                     t->incoming_frame_size,
-                     s->incoming_window_delta +
-                         t->settings[GRPC_ACKED_SETTINGS]
-                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
-        grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
-        gpr_free(msg);
-        return err;
-      }
-    }
-
-    GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s,
-                                                        incoming_frame_size);
-    if ((int64_t)s->incoming_window_delta - (int64_t)s->announce_window <=
-        -(int64_t)t->settings[GRPC_SENT_SETTINGS]
-                             [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] /
-            2) {
-      grpc_chttp2_become_writable(exec_ctx, t, s,
-                                  GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
-                                  "window-update-required");
-    }
-    s->received_bytes += incoming_frame_size;
-  }
-
-  uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
-  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
-                                   incoming_frame_size);
-  if (t->incoming_window <= target_incoming_window / 2) {
-    grpc_chttp2_initiate_write(exec_ctx, t, "flow_control");
-  }
-
-  return GRPC_ERROR_NONE;
-}
-
 static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx,
                                           grpc_chttp2_transport *t) {
   grpc_chttp2_stream *s =
       grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
   grpc_error *err = GRPC_ERROR_NONE;
-  err = update_incoming_window(exec_ctx, t, s);
+  err = grpc_chttp2_flowctl_recv_data(&t->flow_control,
+                                      s == NULL ? NULL : &s->flow_control,
+                                      t->incoming_frame_size);
+  grpc_chttp2_act_on_flowctl_action(
+      exec_ctx, grpc_chttp2_flowctl_get_action(
+                    &t->flow_control, s == NULL ? NULL : &s->flow_control),
+      t, s);
   if (err != GRPC_ERROR_NONE) {
     goto error_handler;
   }
   if (s == NULL) {
     return init_skip_frame_parser(exec_ctx, t, 0);
   }
+  s->received_bytes += t->incoming_frame_size;
   s->stats.incoming.framing_bytes += 9;
   if (err == GRPC_ERROR_NONE && s->read_closed) {
     return init_skip_frame_parser(exec_ctx, t, 0);
@@ -657,6 +589,10 @@
           "ignoring grpc_chttp2_stream with non-client generated index %d",
           t->incoming_stream_id));
       return init_skip_frame_parser(exec_ctx, t, 1);
+    } else if (grpc_chttp2_stream_map_size(&t->stream_map) >=
+               t->settings[GRPC_ACKED_SETTINGS]
+                          [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded");
     }
     t->last_new_stream_id = t->incoming_stream_id;
     s = t->incoming_stream =
diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c
index 1bf5b345..7cc85de 100644
--- a/src/core/ext/transport/chttp2/transport/stream_lists.c
+++ b/src/core/ext/transport/chttp2/transport/stream_lists.c
@@ -150,12 +150,17 @@
 
 void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
                                                grpc_chttp2_stream *s) {
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      gpr_log(GPR_DEBUG, "stream %u stalled by transport", s->id));
   stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
 }
 
 bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
                                                grpc_chttp2_stream **s) {
-  return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+  bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+  GRPC_FLOW_CONTROL_IF_TRACING(if (ret) gpr_log(
+      GPR_DEBUG, "stream %u un-stalled by transport", (*s)->id));
+  return ret;
 }
 
 void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
@@ -165,15 +170,23 @@
 
 void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
                                             grpc_chttp2_stream *s) {
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      gpr_log(GPR_DEBUG, "stream %u stalled by stream", s->id));
   stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
 }
 
 bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
                                             grpc_chttp2_stream **s) {
-  return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+  bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", (*s)->id));
+  return ret;
 }
 
 bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
                                                grpc_chttp2_stream *s) {
-  return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+  bool ret = stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+  GRPC_FLOW_CONTROL_IF_TRACING(
+      if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", s->id));
+  return ret;
 }
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index 315f2a6..80eb51f 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -148,15 +148,6 @@
   return true;
 }
 
-/* How many bytes of incoming flow control would we like to advertise */
-uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) {
-  return (uint32_t)GPR_MIN(
-      (int64_t)((1u << 31) - 1),
-      t->stream_total_over_incoming_window +
-          t->settings[GRPC_SENT_SETTINGS]
-                     [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
-}
-
 /* How many bytes would we like to put on the wire during a single syscall */
 static uint32_t target_write_size(grpc_chttp2_transport *t) {
   return 1024 * 1024;
@@ -201,7 +192,7 @@
       &t->hpack_compressor,
       t->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
 
-  if (t->outgoing_window > 0) {
+  if (t->flow_control.remote_window > 0) {
     while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
       if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) &&
           stream_ref_if_not_destroyed(&s->refcount->refs)) {
@@ -227,10 +218,12 @@
     bool sent_initial_metadata = s->sent_initial_metadata;
     bool now_writing = false;
 
-    GRPC_CHTTP2_IF_TRACING(gpr_log(
-        GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t,
-        t->is_client ? "CLIENT" : "SERVER", s->id, sent_initial_metadata,
-        s->send_initial_metadata != NULL, s->announce_window));
+    GRPC_CHTTP2_IF_TRACING(
+        gpr_log(GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t,
+                t->is_client ? "CLIENT" : "SERVER", s->id,
+                sent_initial_metadata, s->send_initial_metadata != NULL,
+                (int)(s->flow_control.local_window_delta -
+                      s->flow_control.announced_window_delta)));
 
     grpc_mdelem *extra_headers_for_trailing_metadata[2];
     size_t num_extra_headers_for_trailing_metadata = 0;
@@ -287,11 +280,12 @@
       sent_initial_metadata = true;
     }
     /* send any window updates */
-    if (s->announce_window > 0) {
-      uint32_t announce = s->announce_window;
-      grpc_slice_buffer_add(&t->outbuf,
-                            grpc_chttp2_window_update_create(
-                                s->id, s->announce_window, &s->stats.outgoing));
+    uint32_t stream_announce = grpc_chttp2_flowctl_maybe_send_stream_update(
+        &t->flow_control, &s->flow_control);
+    if (stream_announce > 0) {
+      grpc_slice_buffer_add(
+          &t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce,
+                                                       &s->stats.outgoing));
       t->ping_state.pings_before_data_required =
           t->ping_policy.max_pings_without_data;
       if (!t->is_client) {
@@ -299,36 +293,75 @@
             gpr_inf_past(GPR_CLOCK_MONOTONIC);
         t->ping_recv_state.ping_strikes = 0;
       }
-      GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, announce_window, announce);
     }
     if (sent_initial_metadata) {
       /* send any body bytes, if allowed by flow control */
-      if (s->flow_controlled_buffer.length > 0) {
-        uint32_t stream_outgoing_window = (uint32_t)GPR_MAX(
+      if (s->flow_controlled_buffer.length > 0 ||
+          (s->stream_compression_send_enabled &&
+           s->compressed_data_buffer->length > 0)) {
+        uint32_t stream_remote_window = (uint32_t)GPR_MAX(
             0,
-            s->outgoing_window_delta +
+            s->flow_control.remote_window_delta +
                 (int64_t)t->settings[GRPC_PEER_SETTINGS]
                                     [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
         uint32_t max_outgoing = (uint32_t)GPR_MIN(
             t->settings[GRPC_PEER_SETTINGS]
                        [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-            GPR_MIN(stream_outgoing_window, t->outgoing_window));
+            GPR_MIN(stream_remote_window, t->flow_control.remote_window));
         if (max_outgoing > 0) {
-          uint32_t send_bytes =
-              (uint32_t)GPR_MIN(max_outgoing, s->flow_controlled_buffer.length);
-          bool is_last_data_frame =
-              s->fetching_send_message == NULL &&
-              send_bytes == s->flow_controlled_buffer.length;
-          bool is_last_frame =
-              is_last_data_frame && s->send_trailing_metadata != NULL &&
-              grpc_metadata_batch_is_empty(s->send_trailing_metadata);
-          grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, send_bytes,
-                                  is_last_frame, &s->stats.outgoing,
-                                  &t->outbuf);
-          GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window_delta,
-                                        send_bytes);
-          GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, outgoing_window,
-                                           send_bytes);
+          bool is_last_data_frame = false;
+          bool is_last_frame = false;
+          if (s->stream_compression_send_enabled) {
+            while ((s->flow_controlled_buffer.length > 0 ||
+                    s->compressed_data_buffer->length > 0) &&
+                   max_outgoing > 0) {
+              if (s->compressed_data_buffer->length > 0) {
+                uint32_t send_bytes = (uint32_t)GPR_MIN(
+                    max_outgoing, s->compressed_data_buffer->length);
+                is_last_data_frame =
+                    (send_bytes == s->compressed_data_buffer->length &&
+                     s->flow_controlled_buffer.length == 0 &&
+                     s->fetching_send_message == NULL);
+                is_last_frame =
+                    is_last_data_frame && s->send_trailing_metadata != NULL &&
+                    grpc_metadata_batch_is_empty(s->send_trailing_metadata);
+                grpc_chttp2_encode_data(s->id, s->compressed_data_buffer,
+                                        send_bytes, is_last_frame,
+                                        &s->stats.outgoing, &t->outbuf);
+                grpc_chttp2_flowctl_sent_data(&t->flow_control,
+                                              &s->flow_control, send_bytes);
+                max_outgoing -= send_bytes;
+                if (s->compressed_data_buffer->length == 0) {
+                  s->sending_bytes += s->uncompressed_data_size;
+                }
+              } else {
+                if (s->stream_compression_ctx == NULL) {
+                  s->stream_compression_ctx =
+                      grpc_stream_compression_context_create(
+                          GRPC_STREAM_COMPRESSION_COMPRESS);
+                }
+                s->uncompressed_data_size = s->flow_controlled_buffer.length;
+                GPR_ASSERT(grpc_stream_compress(
+                    s->stream_compression_ctx, &s->flow_controlled_buffer,
+                    s->compressed_data_buffer, NULL, MAX_SIZE_T,
+                    GRPC_STREAM_COMPRESSION_FLUSH_SYNC));
+              }
+            }
+          } else {
+            uint32_t send_bytes = (uint32_t)GPR_MIN(
+                max_outgoing, s->flow_controlled_buffer.length);
+            is_last_data_frame = s->fetching_send_message == NULL &&
+                                 send_bytes == s->flow_controlled_buffer.length;
+            is_last_frame =
+                is_last_data_frame && s->send_trailing_metadata != NULL &&
+                grpc_metadata_batch_is_empty(s->send_trailing_metadata);
+            grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer,
+                                    send_bytes, is_last_frame,
+                                    &s->stats.outgoing, &t->outbuf);
+            grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
+                                          send_bytes);
+            s->sending_bytes += send_bytes;
+          }
           t->ping_state.pings_before_data_required =
               t->ping_policy.max_pings_without_data;
           if (!t->is_client) {
@@ -345,23 +378,26 @@
                                                     &s->stats.outgoing));
             }
           }
-          s->sending_bytes += send_bytes;
           now_writing = true;
-          if (s->flow_controlled_buffer.length > 0) {
+          if (s->flow_controlled_buffer.length > 0 ||
+              (s->stream_compression_send_enabled &&
+               s->compressed_data_buffer->length > 0)) {
             GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork");
             grpc_chttp2_list_add_writable_stream(t, s);
           }
-        } else if (t->outgoing_window == 0) {
+        } else if (t->flow_control.remote_window == 0) {
           grpc_chttp2_list_add_stalled_by_transport(t, s);
           now_writing = true;
-        } else if (stream_outgoing_window == 0) {
+        } else if (stream_remote_window == 0) {
           grpc_chttp2_list_add_stalled_by_stream(t, s);
           now_writing = true;
         }
       }
       if (s->send_trailing_metadata != NULL &&
           s->fetching_send_message == NULL &&
-          s->flow_controlled_buffer.length == 0) {
+          s->flow_controlled_buffer.length == 0 &&
+          (!s->stream_compression_send_enabled ||
+           s->compressed_data_buffer->length == 0)) {
         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
         if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
           grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
@@ -406,22 +442,15 @@
     }
   }
 
-  /* if the grpc_chttp2_transport is ready to send a window update, do so here
-     also; 3/4 is a magic number that will likely get tuned soon */
-  uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
-  uint32_t threshold_to_send_transport_window_update =
-      t->outbuf.count > 0 ? 3 * target_incoming_window / 4
-                          : target_incoming_window / 2;
-  if (t->incoming_window <= threshold_to_send_transport_window_update &&
-      t->incoming_window != target_incoming_window) {
+  uint32_t transport_announce =
+      grpc_chttp2_flowctl_maybe_send_transport_update(&t->flow_control);
+  if (transport_announce) {
     maybe_initiate_ping(exec_ctx, t,
                         GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE);
-    uint32_t announced = (uint32_t)GPR_CLAMP(
-        target_incoming_window - t->incoming_window, 0, UINT32_MAX);
-    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("write", t, incoming_window, announced);
     grpc_transport_one_way_stats throwaway_stats;
-    grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_window_update_create(
-                                          0, announced, &throwaway_stats));
+    grpc_slice_buffer_add(
+        &t->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
+                                                     &throwaway_stats));
     t->ping_state.pings_before_data_required =
         t->ping_policy.max_pings_without_data;
     if (!t->is_client) {
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 29dfa88..776e076 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -968,6 +968,9 @@
     s->header_array.capacity = s->header_array.count;
     CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
     bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false);
+    if (url) {
+      gpr_free(url);
+    }
     unsigned int header_index;
     for (header_index = 0; header_index < s->header_array.count;
          header_index++) {
diff --git a/src/core/ext/transport/inproc/inproc_plugin.c b/src/core/ext/transport/inproc/inproc_plugin.c
new file mode 100644
index 0000000..6a796a0
--- /dev/null
+++ b/src/core/ext/transport/inproc/inproc_plugin.c
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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 "src/core/ext/transport/inproc/inproc_transport.h"
+#include "src/core/lib/debug/trace.h"
+
+grpc_tracer_flag grpc_inproc_trace = GRPC_TRACER_INITIALIZER(false, "inproc");
+
+void grpc_inproc_plugin_init(void) {
+  grpc_register_tracer(&grpc_inproc_trace);
+  grpc_inproc_transport_init();
+}
+
+void grpc_inproc_plugin_shutdown(void) { grpc_inproc_transport_shutdown(); }
diff --git a/src/core/ext/transport/inproc/inproc_transport.c b/src/core/ext/transport/inproc/inproc_transport.c
new file mode 100644
index 0000000..6f4b429
--- /dev/null
+++ b/src/core/ext/transport/inproc/inproc_transport.c
@@ -0,0 +1,1303 @@
+/*
+ *
+ * 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 "src/core/ext/transport/inproc/inproc_transport.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+#include <string.h>
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/surface/server.h"
+#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+#define INPROC_LOG(...)                                          \
+  do {                                                           \
+    if (GRPC_TRACER_ON(grpc_inproc_trace)) gpr_log(__VA_ARGS__); \
+  } while (0)
+
+static const grpc_transport_vtable inproc_vtable;
+static grpc_slice g_empty_slice;
+static grpc_slice g_fake_path_key;
+static grpc_slice g_fake_path_value;
+static grpc_slice g_fake_auth_key;
+static grpc_slice g_fake_auth_value;
+
+typedef struct {
+  gpr_mu mu;
+  gpr_refcount refs;
+} shared_mu;
+
+typedef struct inproc_transport {
+  grpc_transport base;
+  shared_mu *mu;
+  gpr_refcount refs;
+  bool is_client;
+  grpc_connectivity_state_tracker connectivity;
+  void (*accept_stream_cb)(grpc_exec_ctx *exec_ctx, void *user_data,
+                           grpc_transport *transport, const void *server_data);
+  void *accept_stream_data;
+  bool is_closed;
+  struct inproc_transport *other_side;
+  struct inproc_stream *stream_list;
+} inproc_transport;
+
+typedef struct sb_list_entry {
+  grpc_slice_buffer sb;
+  struct sb_list_entry *next;
+} sb_list_entry;
+
+// Specialize grpc_byte_stream for our use case
+typedef struct {
+  grpc_byte_stream base;
+  sb_list_entry *le;
+  grpc_error *shutdown_error;
+} inproc_slice_byte_stream;
+
+typedef struct {
+  // TODO (vjpai): Add some inlined elements to avoid alloc in simple cases
+  sb_list_entry *head;
+  sb_list_entry *tail;
+} slice_buffer_list;
+
+static void slice_buffer_list_init(slice_buffer_list *l) {
+  l->head = NULL;
+  l->tail = NULL;
+}
+
+static void sb_list_entry_destroy(grpc_exec_ctx *exec_ctx, sb_list_entry *le) {
+  grpc_slice_buffer_destroy_internal(exec_ctx, &le->sb);
+  gpr_free(le);
+}
+
+static void slice_buffer_list_destroy(grpc_exec_ctx *exec_ctx,
+                                      slice_buffer_list *l) {
+  sb_list_entry *curr = l->head;
+  while (curr != NULL) {
+    sb_list_entry *le = curr;
+    curr = curr->next;
+    sb_list_entry_destroy(exec_ctx, le);
+  }
+  l->head = NULL;
+  l->tail = NULL;
+}
+
+static bool slice_buffer_list_empty(slice_buffer_list *l) {
+  return l->head == NULL;
+}
+
+static void slice_buffer_list_append_entry(slice_buffer_list *l,
+                                           sb_list_entry *next) {
+  next->next = NULL;
+  if (l->tail) {
+    l->tail->next = next;
+    l->tail = next;
+  } else {
+    l->head = next;
+    l->tail = next;
+  }
+}
+
+static grpc_slice_buffer *slice_buffer_list_append(slice_buffer_list *l) {
+  sb_list_entry *next = gpr_malloc(sizeof(*next));
+  grpc_slice_buffer_init(&next->sb);
+  slice_buffer_list_append_entry(l, next);
+  return &next->sb;
+}
+
+static sb_list_entry *slice_buffer_list_pophead(slice_buffer_list *l) {
+  sb_list_entry *ret = l->head;
+  l->head = l->head->next;
+  if (l->head == NULL) {
+    l->tail = NULL;
+  }
+  return ret;
+}
+
+typedef struct inproc_stream {
+  inproc_transport *t;
+  grpc_metadata_batch to_read_initial_md;
+  uint32_t to_read_initial_md_flags;
+  bool to_read_initial_md_filled;
+  slice_buffer_list to_read_message;
+  grpc_metadata_batch to_read_trailing_md;
+  bool to_read_trailing_md_filled;
+  bool reads_needed;
+  bool read_closure_scheduled;
+  grpc_closure read_closure;
+  // Write buffer used only during gap at init time when client-side
+  // stream is set up but server side stream is not yet set up
+  grpc_metadata_batch write_buffer_initial_md;
+  bool write_buffer_initial_md_filled;
+  uint32_t write_buffer_initial_md_flags;
+  gpr_timespec write_buffer_deadline;
+  slice_buffer_list write_buffer_message;
+  grpc_metadata_batch write_buffer_trailing_md;
+  bool write_buffer_trailing_md_filled;
+  grpc_error *write_buffer_cancel_error;
+
+  struct inproc_stream *other_side;
+  bool other_side_closed;               // won't talk anymore
+  bool write_buffer_other_side_closed;  // on hold
+  grpc_stream_refcount *refs;
+  grpc_closure *closure_at_destroy;
+
+  gpr_arena *arena;
+
+  grpc_transport_stream_op_batch *recv_initial_md_op;
+  grpc_transport_stream_op_batch *recv_message_op;
+  grpc_transport_stream_op_batch *recv_trailing_md_op;
+
+  inproc_slice_byte_stream recv_message_stream;
+
+  bool initial_md_sent;
+  bool trailing_md_sent;
+  bool initial_md_recvd;
+  bool trailing_md_recvd;
+
+  bool closed;
+
+  grpc_error *cancel_self_error;
+  grpc_error *cancel_other_error;
+
+  gpr_timespec deadline;
+
+  bool listed;
+  struct inproc_stream *stream_list_prev;
+  struct inproc_stream *stream_list_next;
+} inproc_stream;
+
+static bool inproc_slice_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                                          grpc_byte_stream *bs, size_t max,
+                                          grpc_closure *on_complete) {
+  // Because inproc transport always provides the entire message atomically,
+  // the byte stream always has data available when this function is called.
+  // Thus, this function always returns true (unlike other transports) and
+  // there is never any need to schedule a closure
+  return true;
+}
+
+static grpc_error *inproc_slice_byte_stream_pull(grpc_exec_ctx *exec_ctx,
+                                                 grpc_byte_stream *bs,
+                                                 grpc_slice *slice) {
+  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
+  if (stream->shutdown_error != GRPC_ERROR_NONE) {
+    return GRPC_ERROR_REF(stream->shutdown_error);
+  }
+  *slice = grpc_slice_buffer_take_first(&stream->le->sb);
+  return GRPC_ERROR_NONE;
+}
+
+static void inproc_slice_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                                              grpc_byte_stream *bs,
+                                              grpc_error *error) {
+  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+  stream->shutdown_error = error;
+}
+
+static void inproc_slice_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
+                                             grpc_byte_stream *bs) {
+  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
+  sb_list_entry_destroy(exec_ctx, stream->le);
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+}
+
+static const grpc_byte_stream_vtable inproc_slice_byte_stream_vtable = {
+    inproc_slice_byte_stream_next, inproc_slice_byte_stream_pull,
+    inproc_slice_byte_stream_shutdown, inproc_slice_byte_stream_destroy};
+
+void inproc_slice_byte_stream_init(inproc_slice_byte_stream *s,
+                                   sb_list_entry *le) {
+  s->base.length = (uint32_t)le->sb.length;
+  s->base.flags = 0;
+  s->base.vtable = &inproc_slice_byte_stream_vtable;
+  s->le = le;
+  s->shutdown_error = GRPC_ERROR_NONE;
+}
+
+static void ref_transport(inproc_transport *t) {
+  INPROC_LOG(GPR_DEBUG, "ref_transport %p", t);
+  gpr_ref(&t->refs);
+}
+
+static void really_destroy_transport(grpc_exec_ctx *exec_ctx,
+                                     inproc_transport *t) {
+  INPROC_LOG(GPR_DEBUG, "really_destroy_transport %p", t);
+  grpc_connectivity_state_destroy(exec_ctx, &t->connectivity);
+  if (gpr_unref(&t->mu->refs)) {
+    gpr_free(t->mu);
+  }
+  gpr_free(t);
+}
+
+static void unref_transport(grpc_exec_ctx *exec_ctx, inproc_transport *t) {
+  INPROC_LOG(GPR_DEBUG, "unref_transport %p", t);
+  if (gpr_unref(&t->refs)) {
+    really_destroy_transport(exec_ctx, t);
+  }
+}
+
+#ifndef NDEBUG
+#define STREAM_REF(refs, reason) grpc_stream_ref(refs, reason)
+#define STREAM_UNREF(e, refs, reason) grpc_stream_unref(e, refs, reason)
+#else
+#define STREAM_REF(refs, reason) grpc_stream_ref(refs)
+#define STREAM_UNREF(e, refs, reason) grpc_stream_unref(e, refs)
+#endif
+
+static void ref_stream(inproc_stream *s, const char *reason) {
+  INPROC_LOG(GPR_DEBUG, "ref_stream %p %s", s, reason);
+  STREAM_REF(s->refs, reason);
+}
+
+static void unref_stream(grpc_exec_ctx *exec_ctx, inproc_stream *s,
+                         const char *reason) {
+  INPROC_LOG(GPR_DEBUG, "unref_stream %p %s", s, reason);
+  STREAM_UNREF(exec_ctx, s->refs, reason);
+}
+
+static void really_destroy_stream(grpc_exec_ctx *exec_ctx, inproc_stream *s) {
+  INPROC_LOG(GPR_DEBUG, "really_destroy_stream %p", s);
+
+  slice_buffer_list_destroy(exec_ctx, &s->to_read_message);
+  slice_buffer_list_destroy(exec_ctx, &s->write_buffer_message);
+  GRPC_ERROR_UNREF(s->write_buffer_cancel_error);
+  GRPC_ERROR_UNREF(s->cancel_self_error);
+  GRPC_ERROR_UNREF(s->cancel_other_error);
+
+  unref_transport(exec_ctx, s->t);
+
+  if (s->closure_at_destroy) {
+    GRPC_CLOSURE_SCHED(exec_ctx, s->closure_at_destroy, GRPC_ERROR_NONE);
+  }
+}
+
+static void read_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
+                               grpc_error *error);
+
+static void log_metadata(const grpc_metadata_batch *md_batch, bool is_client,
+                         bool is_initial) {
+  for (grpc_linked_mdelem *md = md_batch->list.head; md != NULL;
+       md = md->next) {
+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
+    char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
+    gpr_log(GPR_INFO, "INPROC:%s:%s: %s: %s", is_initial ? "HDR" : "TRL",
+            is_client ? "CLI" : "SVR", key, value);
+    gpr_free(key);
+    gpr_free(value);
+  }
+}
+
+static grpc_error *fill_in_metadata(grpc_exec_ctx *exec_ctx, inproc_stream *s,
+                                    const grpc_metadata_batch *metadata,
+                                    uint32_t flags, grpc_metadata_batch *out_md,
+                                    uint32_t *outflags, bool *markfilled) {
+  if (GRPC_TRACER_ON(grpc_inproc_trace)) {
+    log_metadata(metadata, s->t->is_client, outflags != NULL);
+  }
+
+  if (outflags != NULL) {
+    *outflags = flags;
+  }
+  if (markfilled != NULL) {
+    *markfilled = true;
+  }
+  grpc_error *error = GRPC_ERROR_NONE;
+  for (grpc_linked_mdelem *elem = metadata->list.head;
+       (elem != NULL) && (error == GRPC_ERROR_NONE); elem = elem->next) {
+    grpc_linked_mdelem *nelem = gpr_arena_alloc(s->arena, sizeof(*nelem));
+    nelem->md = grpc_mdelem_from_slices(
+        exec_ctx, grpc_slice_intern(GRPC_MDKEY(elem->md)),
+        grpc_slice_intern(GRPC_MDVALUE(elem->md)));
+
+    error = grpc_metadata_batch_link_tail(exec_ctx, out_md, nelem);
+  }
+  return error;
+}
+
+static int init_stream(grpc_exec_ctx *exec_ctx, 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_transport *t = (inproc_transport *)gt;
+  inproc_stream *s = (inproc_stream *)gs;
+  s->arena = arena;
+
+  s->refs = refcount;
+  // Ref this stream right now
+  ref_stream(s, "inproc_init_stream:init");
+
+  grpc_metadata_batch_init(&s->to_read_initial_md);
+  s->to_read_initial_md_flags = 0;
+  s->to_read_initial_md_filled = false;
+  grpc_metadata_batch_init(&s->to_read_trailing_md);
+  s->to_read_trailing_md_filled = false;
+  grpc_metadata_batch_init(&s->write_buffer_initial_md);
+  s->write_buffer_initial_md_flags = 0;
+  s->write_buffer_initial_md_filled = false;
+  grpc_metadata_batch_init(&s->write_buffer_trailing_md);
+  s->write_buffer_trailing_md_filled = false;
+  slice_buffer_list_init(&s->to_read_message);
+  slice_buffer_list_init(&s->write_buffer_message);
+  s->reads_needed = false;
+  s->read_closure_scheduled = false;
+  GRPC_CLOSURE_INIT(&s->read_closure, read_state_machine, s,
+                    grpc_schedule_on_exec_ctx);
+  s->t = t;
+  s->closure_at_destroy = NULL;
+  s->other_side_closed = false;
+
+  s->initial_md_sent = s->trailing_md_sent = s->initial_md_recvd =
+      s->trailing_md_recvd = false;
+
+  s->closed = false;
+
+  s->cancel_self_error = GRPC_ERROR_NONE;
+  s->cancel_other_error = GRPC_ERROR_NONE;
+  s->write_buffer_cancel_error = GRPC_ERROR_NONE;
+  s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  s->write_buffer_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+
+  s->stream_list_prev = NULL;
+  gpr_mu_lock(&t->mu->mu);
+  s->listed = true;
+  ref_stream(s, "inproc_init_stream:list");
+  s->stream_list_next = t->stream_list;
+  if (t->stream_list) {
+    t->stream_list->stream_list_prev = s;
+  }
+  t->stream_list = s;
+  gpr_mu_unlock(&t->mu->mu);
+
+  if (!server_data) {
+    ref_transport(t);
+    inproc_transport *st = t->other_side;
+    ref_transport(st);
+    s->other_side = NULL;  // will get filled in soon
+    // 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);
+    (*st->accept_stream_cb)(exec_ctx, st->accept_stream_data, &st->base,
+                            (void *)s);
+  } else {
+    // This is the server-side and is being called through accept_stream_cb
+    inproc_stream *cs = (inproc_stream *)server_data;
+    s->other_side = cs;
+    // Ref the server-side stream on behalf of the client now
+    ref_stream(s, "inproc_init_stream:srv");
+
+    // Now we are about to affect the other side, so lock the transport
+    // to make sure that it doesn't get destroyed
+    gpr_mu_lock(&s->t->mu->mu);
+    cs->other_side = s;
+    // Now transfer from the other side's write_buffer if any to the to_read
+    // buffer
+    if (cs->write_buffer_initial_md_filled) {
+      fill_in_metadata(exec_ctx, s, &cs->write_buffer_initial_md,
+                       cs->write_buffer_initial_md_flags,
+                       &s->to_read_initial_md, &s->to_read_initial_md_flags,
+                       &s->to_read_initial_md_filled);
+      s->deadline = gpr_time_min(s->deadline, cs->write_buffer_deadline);
+      grpc_metadata_batch_clear(exec_ctx, &cs->write_buffer_initial_md);
+      cs->write_buffer_initial_md_filled = false;
+    }
+    while (!slice_buffer_list_empty(&cs->write_buffer_message)) {
+      slice_buffer_list_append_entry(
+          &s->to_read_message,
+          slice_buffer_list_pophead(&cs->write_buffer_message));
+    }
+    if (cs->write_buffer_trailing_md_filled) {
+      fill_in_metadata(exec_ctx, s, &cs->write_buffer_trailing_md, 0,
+                       &s->to_read_trailing_md, NULL,
+                       &s->to_read_trailing_md_filled);
+      grpc_metadata_batch_clear(exec_ctx, &cs->write_buffer_trailing_md);
+      cs->write_buffer_trailing_md_filled = false;
+    }
+    if (cs->write_buffer_cancel_error != GRPC_ERROR_NONE) {
+      s->cancel_other_error = cs->write_buffer_cancel_error;
+      cs->write_buffer_cancel_error = GRPC_ERROR_NONE;
+    }
+
+    gpr_mu_unlock(&s->t->mu->mu);
+  }
+  return 0;  // return value is not important
+}
+
+static void close_stream_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s) {
+  if (!s->closed) {
+    // Release the metadata that we would have written out
+    grpc_metadata_batch_destroy(exec_ctx, &s->write_buffer_initial_md);
+    grpc_metadata_batch_destroy(exec_ctx, &s->write_buffer_trailing_md);
+
+    if (s->listed) {
+      inproc_stream *p = s->stream_list_prev;
+      inproc_stream *n = s->stream_list_next;
+      if (p != NULL) {
+        p->stream_list_next = n;
+      } else {
+        s->t->stream_list = n;
+      }
+      if (n != NULL) {
+        n->stream_list_prev = p;
+      }
+      s->listed = false;
+      unref_stream(exec_ctx, s, "close_stream:list");
+    }
+    s->closed = true;
+    unref_stream(exec_ctx, s, "close_stream:closing");
+  }
+}
+
+// This function means that we are done talking/listening to the other side
+static void close_other_side_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s,
+                                    const char *reason) {
+  if (s->other_side != NULL) {
+    // First release the metadata that came from the other side's arena
+    grpc_metadata_batch_destroy(exec_ctx, &s->to_read_initial_md);
+    grpc_metadata_batch_destroy(exec_ctx, &s->to_read_trailing_md);
+
+    unref_stream(exec_ctx, s->other_side, reason);
+    s->other_side_closed = true;
+    s->other_side = NULL;
+  } else if (!s->other_side_closed) {
+    s->write_buffer_other_side_closed = true;
+  }
+}
+
+static void fail_helper_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s,
+                               grpc_error *error) {
+  INPROC_LOG(GPR_DEBUG, "read_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) {
+    // Send trailing md to the other side indicating cancellation
+    s->trailing_md_sent = true;
+
+    grpc_metadata_batch fake_md;
+    grpc_metadata_batch_init(&fake_md);
+
+    inproc_stream *other = s->other_side;
+    grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md
+                                                : &other->to_read_trailing_md;
+    bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled
+                                       : &other->to_read_trailing_md_filled;
+    fill_in_metadata(exec_ctx, s, &fake_md, 0, dest, NULL, destfilled);
+    grpc_metadata_batch_destroy(exec_ctx, &fake_md);
+
+    if (other != NULL) {
+      if (other->cancel_other_error == GRPC_ERROR_NONE) {
+        other->cancel_other_error = GRPC_ERROR_REF(error);
+      }
+      if (other->reads_needed) {
+        if (!other->read_closure_scheduled) {
+          GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure,
+                             GRPC_ERROR_REF(error));
+          other->read_closure_scheduled = true;
+        }
+        other->reads_needed = false;
+      }
+    } else if (s->write_buffer_cancel_error == GRPC_ERROR_NONE) {
+      s->write_buffer_cancel_error = GRPC_ERROR_REF(error);
+    }
+  }
+  if (s->recv_initial_md_op) {
+    grpc_error *err;
+    if (!s->t->is_client) {
+      // If this is a server, provide initial metadata with a path and authority
+      // since it expects that as well as no error yet
+      grpc_metadata_batch fake_md;
+      grpc_metadata_batch_init(&fake_md);
+      grpc_linked_mdelem *path_md = gpr_arena_alloc(s->arena, sizeof(*path_md));
+      path_md->md =
+          grpc_mdelem_from_slices(exec_ctx, g_fake_path_key, g_fake_path_value);
+      GPR_ASSERT(grpc_metadata_batch_link_tail(exec_ctx, &fake_md, path_md) ==
+                 GRPC_ERROR_NONE);
+      grpc_linked_mdelem *auth_md = gpr_arena_alloc(s->arena, sizeof(*auth_md));
+      auth_md->md =
+          grpc_mdelem_from_slices(exec_ctx, g_fake_auth_key, g_fake_auth_value);
+      GPR_ASSERT(grpc_metadata_batch_link_tail(exec_ctx, &fake_md, auth_md) ==
+                 GRPC_ERROR_NONE);
+
+      fill_in_metadata(
+          exec_ctx, s, &fake_md, 0,
+          s->recv_initial_md_op->payload->recv_initial_metadata
+              .recv_initial_metadata,
+          s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags,
+          NULL);
+      grpc_metadata_batch_destroy(exec_ctx, &fake_md);
+      err = GRPC_ERROR_NONE;
+    } else {
+      err = GRPC_ERROR_REF(error);
+    }
+    INPROC_LOG(GPR_DEBUG,
+               "fail_helper %p scheduling initial-metadata-ready %p %p", s,
+               error, err);
+    GRPC_CLOSURE_SCHED(exec_ctx,
+                       s->recv_initial_md_op->payload->recv_initial_metadata
+                           .recv_initial_metadata_ready,
+                       err);
+    // Last use of err so no need to REF and then UNREF it
+
+    if ((s->recv_initial_md_op != s->recv_message_op) &&
+        (s->recv_initial_md_op != s->recv_trailing_md_op)) {
+      INPROC_LOG(GPR_DEBUG,
+                 "fail_helper %p scheduling initial-metadata-on-complete %p",
+                 error, s);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->on_complete,
+                         GRPC_ERROR_REF(error));
+    }
+    s->recv_initial_md_op = NULL;
+  }
+  if (s->recv_message_op) {
+    INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-ready %p", s,
+               error);
+    GRPC_CLOSURE_SCHED(
+        exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
+        GRPC_ERROR_REF(error));
+    if (s->recv_message_op != s->recv_trailing_md_op) {
+      INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-on-complete %p",
+                 s, error);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
+                         GRPC_ERROR_REF(error));
+    }
+    s->recv_message_op = NULL;
+  }
+  if (s->recv_trailing_md_op) {
+    INPROC_LOG(GPR_DEBUG,
+               "fail_helper %p scheduling trailing-md-on-complete %p", s,
+               error);
+    GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
+                       GRPC_ERROR_REF(error));
+    s->recv_trailing_md_op = NULL;
+  }
+  close_other_side_locked(exec_ctx, s, "fail_helper:other_side");
+  close_stream_locked(exec_ctx, s);
+
+  GRPC_ERROR_UNREF(error);
+}
+
+static void read_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
+                               grpc_error *error) {
+  // This function gets called when we have contents in the unprocessed reads
+  // Get what we want based on our ops wanted
+  // Schedule our appropriate closures
+  // and then return to reads_needed state if still needed
+
+  // Since this is a closure directly invoked by the combiner, it should not
+  // unref the error parameter explicitly; the combiner will do that implicitly
+  grpc_error *new_err = GRPC_ERROR_NONE;
+
+  bool needs_close = false;
+
+  INPROC_LOG(GPR_DEBUG, "read_state_machine %p", arg);
+  inproc_stream *s = (inproc_stream *)arg;
+  gpr_mu *mu = &s->t->mu->mu;  // keep aside in case s gets closed
+  gpr_mu_lock(mu);
+  s->read_closure_scheduled = false;
+  // cancellation takes precedence
+  if (s->cancel_self_error != GRPC_ERROR_NONE) {
+    fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(s->cancel_self_error));
+    goto done;
+  } else if (s->cancel_other_error != GRPC_ERROR_NONE) {
+    fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(s->cancel_other_error));
+    goto done;
+  } else if (error != GRPC_ERROR_NONE) {
+    fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(error));
+    goto done;
+  }
+
+  if (s->recv_initial_md_op) {
+    if (!s->to_read_initial_md_filled) {
+      // We entered the state machine on some other kind of read even though
+      // we still haven't satisfied initial md . That's an error.
+      new_err =
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unexpected frame sequencing");
+      INPROC_LOG(GPR_DEBUG,
+                 "read_state_machine %p scheduling on_complete errors for no "
+                 "initial md %p",
+                 s, new_err);
+      fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+      goto done;
+    } else if (s->initial_md_recvd) {
+      new_err =
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd initial md");
+      INPROC_LOG(
+          GPR_DEBUG,
+          "read_state_machine %p scheduling on_complete errors for already "
+          "recvd initial md %p",
+          s, new_err);
+      fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+      goto done;
+    }
+
+    s->initial_md_recvd = true;
+    new_err = fill_in_metadata(
+        exec_ctx, s, &s->to_read_initial_md, s->to_read_initial_md_flags,
+        s->recv_initial_md_op->payload->recv_initial_metadata
+            .recv_initial_metadata,
+        s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags, NULL);
+    s->recv_initial_md_op->payload->recv_initial_metadata.recv_initial_metadata
+        ->deadline = s->deadline;
+    grpc_metadata_batch_clear(exec_ctx, &s->to_read_initial_md);
+    s->to_read_initial_md_filled = false;
+    INPROC_LOG(GPR_DEBUG,
+               "read_state_machine %p scheduling initial-metadata-ready %p", s,
+               new_err);
+    GRPC_CLOSURE_SCHED(exec_ctx,
+                       s->recv_initial_md_op->payload->recv_initial_metadata
+                           .recv_initial_metadata_ready,
+                       GRPC_ERROR_REF(new_err));
+    if ((s->recv_initial_md_op != s->recv_message_op) &&
+        (s->recv_initial_md_op != s->recv_trailing_md_op)) {
+      INPROC_LOG(
+          GPR_DEBUG,
+          "read_state_machine %p scheduling initial-metadata-on-complete %p", s,
+          new_err);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->on_complete,
+                         GRPC_ERROR_REF(new_err));
+    }
+    s->recv_initial_md_op = NULL;
+
+    if (new_err != GRPC_ERROR_NONE) {
+      INPROC_LOG(GPR_DEBUG,
+                 "read_state_machine %p scheduling on_complete errors2 %p", s,
+                 new_err);
+      fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+      goto done;
+    }
+  }
+  if (s->to_read_initial_md_filled) {
+    new_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unexpected recv frame");
+    fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+    goto done;
+  }
+  if (!slice_buffer_list_empty(&s->to_read_message) && s->recv_message_op) {
+    inproc_slice_byte_stream_init(
+        &s->recv_message_stream,
+        slice_buffer_list_pophead(&s->to_read_message));
+    *s->recv_message_op->payload->recv_message.recv_message =
+        &s->recv_message_stream.base;
+    INPROC_LOG(GPR_DEBUG, "read_state_machine %p scheduling message-ready", s);
+    GRPC_CLOSURE_SCHED(
+        exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
+        GRPC_ERROR_NONE);
+    if (s->recv_message_op != s->recv_trailing_md_op) {
+      INPROC_LOG(GPR_DEBUG,
+                 "read_state_machine %p scheduling message-on-complete %p", s,
+                 new_err);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
+                         GRPC_ERROR_REF(new_err));
+    }
+    s->recv_message_op = NULL;
+  }
+  if (s->to_read_trailing_md_filled) {
+    if (s->trailing_md_recvd) {
+      new_err =
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd trailing md");
+      INPROC_LOG(
+          GPR_DEBUG,
+          "read_state_machine %p scheduling on_complete errors for already "
+          "recvd trailing md %p",
+          s, new_err);
+      fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+      goto done;
+    }
+    if (s->recv_message_op != NULL) {
+      // This message needs to be wrapped up because it will never be
+      // satisfied
+      INPROC_LOG(GPR_DEBUG, "read_state_machine %p scheduling message-ready",
+                 s);
+      GRPC_CLOSURE_SCHED(
+          exec_ctx,
+          s->recv_message_op->payload->recv_message.recv_message_ready,
+          GRPC_ERROR_NONE);
+      if (s->recv_message_op != s->recv_trailing_md_op) {
+        INPROC_LOG(GPR_DEBUG,
+                   "read_state_machine %p scheduling message-on-complete %p", s,
+                   new_err);
+        GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
+                           GRPC_ERROR_REF(new_err));
+      }
+      s->recv_message_op = NULL;
+    }
+    if (s->recv_trailing_md_op != NULL) {
+      // We wanted trailing metadata and we got it
+      s->trailing_md_recvd = true;
+      new_err =
+          fill_in_metadata(exec_ctx, s, &s->to_read_trailing_md, 0,
+                           s->recv_trailing_md_op->payload
+                               ->recv_trailing_metadata.recv_trailing_metadata,
+                           NULL, NULL);
+      grpc_metadata_batch_clear(exec_ctx, &s->to_read_trailing_md);
+      s->to_read_trailing_md_filled = false;
+
+      // We should schedule the recv_trailing_md_op completion if
+      // 1. this stream is the client-side
+      // 2. this stream is the server-side AND has already sent its trailing md
+      //    (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,
+            "read_state_machine %p scheduling trailing-md-on-complete %p", s,
+            new_err);
+        GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
+                           GRPC_ERROR_REF(new_err));
+        s->recv_trailing_md_op = NULL;
+        needs_close = true;
+      } else {
+        INPROC_LOG(GPR_DEBUG,
+                   "read_state_machine %p server needs to delay handling "
+                   "trailing-md-on-complete %p",
+                   s, new_err);
+      }
+    } else {
+      INPROC_LOG(
+          GPR_DEBUG,
+          "read_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, "read_state_machine %p scheduling message-ready", s);
+    GRPC_CLOSURE_SCHED(
+        exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
+        GRPC_ERROR_NONE);
+    if (s->recv_message_op != s->recv_trailing_md_op) {
+      INPROC_LOG(GPR_DEBUG,
+                 "read_state_machine %p scheduling message-on-complete %p", s,
+                 new_err);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
+                         GRPC_ERROR_REF(new_err));
+    }
+    s->recv_message_op = NULL;
+  }
+  if (s->recv_message_op || s->recv_trailing_md_op) {
+    // Didn't get the item we wanted so we still need to get
+    // rescheduled
+    INPROC_LOG(GPR_DEBUG, "read_state_machine %p still needs closure %p %p", s,
+               s->recv_message_op, s->recv_trailing_md_op);
+    s->reads_needed = true;
+  }
+done:
+  if (needs_close) {
+    close_other_side_locked(exec_ctx, s, "read_state_machine");
+    close_stream_locked(exec_ctx, s);
+  }
+  gpr_mu_unlock(mu);
+  GRPC_ERROR_UNREF(new_err);
+}
+
+static grpc_closure do_nothing_closure;
+
+static bool cancel_stream_locked(grpc_exec_ctx *exec_ctx, 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));
+  if (s->cancel_self_error == GRPC_ERROR_NONE) {
+    ret = true;
+    s->cancel_self_error = GRPC_ERROR_REF(error);
+    if (s->reads_needed) {
+      if (!s->read_closure_scheduled) {
+        GRPC_CLOSURE_SCHED(exec_ctx, &s->read_closure,
+                           GRPC_ERROR_REF(s->cancel_self_error));
+        s->read_closure_scheduled = true;
+      }
+      s->reads_needed = false;
+    }
+    // Send trailing md to the other side indicating cancellation, even if we
+    // already have
+    s->trailing_md_sent = true;
+
+    grpc_metadata_batch cancel_md;
+    grpc_metadata_batch_init(&cancel_md);
+
+    inproc_stream *other = s->other_side;
+    grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md
+                                                : &other->to_read_trailing_md;
+    bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled
+                                       : &other->to_read_trailing_md_filled;
+    fill_in_metadata(exec_ctx, s, &cancel_md, 0, dest, NULL, destfilled);
+    grpc_metadata_batch_destroy(exec_ctx, &cancel_md);
+
+    if (other != NULL) {
+      if (other->cancel_other_error == GRPC_ERROR_NONE) {
+        other->cancel_other_error = GRPC_ERROR_REF(s->cancel_self_error);
+      }
+      if (other->reads_needed) {
+        if (!other->read_closure_scheduled) {
+          GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure,
+                             GRPC_ERROR_REF(other->cancel_other_error));
+          other->read_closure_scheduled = true;
+        }
+        other->reads_needed = false;
+      }
+    } else if (s->write_buffer_cancel_error == GRPC_ERROR_NONE) {
+      s->write_buffer_cancel_error = GRPC_ERROR_REF(s->cancel_self_error);
+    }
+
+    // if we are a server and already received trailing md but
+    // couldn't complete that because we hadn't yet sent out trailing
+    // md, now's the chance
+    if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
+      INPROC_LOG(GPR_DEBUG,
+                 "cancel_stream %p scheduling trailing-md-on-complete %p", s,
+                 s->cancel_self_error);
+      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
+                         GRPC_ERROR_REF(s->cancel_self_error));
+      s->recv_trailing_md_op = NULL;
+    }
+  }
+
+  close_other_side_locked(exec_ctx, s, "cancel_stream:other_side");
+  close_stream_locked(exec_ctx, s);
+
+  GRPC_ERROR_UNREF(error);
+  return ret;
+}
+
+static void perform_stream_op(grpc_exec_ctx *exec_ctx, 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_stream *s = (inproc_stream *)gs;
+  gpr_mu *mu = &s->t->mu->mu;  // save aside in case s gets closed
+  gpr_mu_lock(mu);
+
+  if (GRPC_TRACER_ON(grpc_inproc_trace)) {
+    if (op->send_initial_metadata) {
+      log_metadata(op->payload->send_initial_metadata.send_initial_metadata,
+                   s->t->is_client, true);
+    }
+    if (op->send_trailing_metadata) {
+      log_metadata(op->payload->send_trailing_metadata.send_trailing_metadata,
+                   s->t->is_client, false);
+    }
+  }
+  grpc_error *error = GRPC_ERROR_NONE;
+  grpc_closure *on_complete = op->on_complete;
+  if (on_complete == NULL) {
+    on_complete = &do_nothing_closure;
+  }
+
+  if (op->cancel_stream) {
+    // Call cancel_stream_locked without ref'ing the cancel_error because
+    // this function is responsible to make sure that that field gets unref'ed
+    cancel_stream_locked(exec_ctx, s, op->payload->cancel_stream.cancel_error);
+    // this op can complete without an error
+  } else if (s->cancel_self_error != GRPC_ERROR_NONE) {
+    // 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,
+               op->send_initial_metadata ? " send_initial_metadata" : "",
+               op->send_message ? " send_message" : "",
+               op->send_trailing_metadata ? " send_trailing_metadata" : "",
+               op->recv_initial_metadata ? " recv_initial_metadata" : "",
+               op->recv_message ? " recv_message" : "",
+               op->recv_trailing_metadata ? " recv_trailing_metadata" : "");
+  }
+
+  bool needs_close = false;
+
+  if (error == GRPC_ERROR_NONE &&
+      (op->send_initial_metadata || op->send_message ||
+       op->send_trailing_metadata)) {
+    inproc_stream *other = s->other_side;
+    if (s->t->is_closed) {
+      error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown");
+    }
+    if (error == GRPC_ERROR_NONE && op->send_initial_metadata) {
+      grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_initial_md
+                                                  : &other->to_read_initial_md;
+      uint32_t *destflags = (other == NULL) ? &s->write_buffer_initial_md_flags
+                                            : &other->to_read_initial_md_flags;
+      bool *destfilled = (other == NULL) ? &s->write_buffer_initial_md_filled
+                                         : &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);
+        error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra initial metadata");
+      } else {
+        if (!other->closed) {
+          fill_in_metadata(
+              exec_ctx, s,
+              op->payload->send_initial_metadata.send_initial_metadata,
+              op->payload->send_initial_metadata.send_initial_metadata_flags,
+              dest, destflags, destfilled);
+        }
+        if (s->t->is_client) {
+          gpr_timespec *dl =
+              (other == NULL) ? &s->write_buffer_deadline : &other->deadline;
+          *dl = gpr_time_min(*dl, op->payload->send_initial_metadata
+                                      .send_initial_metadata->deadline);
+          s->initial_md_sent = true;
+        }
+      }
+    }
+    if (error == GRPC_ERROR_NONE && op->send_message) {
+      size_t remaining = op->payload->send_message.send_message->length;
+      grpc_slice_buffer *dest = slice_buffer_list_append(
+          (other == NULL) ? &s->write_buffer_message : &other->to_read_message);
+      do {
+        grpc_slice message_slice;
+        grpc_closure unused;
+        GPR_ASSERT(grpc_byte_stream_next(exec_ctx,
+                                         op->payload->send_message.send_message,
+                                         SIZE_MAX, &unused));
+        error = grpc_byte_stream_pull(
+            exec_ctx, op->payload->send_message.send_message, &message_slice);
+        if (error != GRPC_ERROR_NONE) {
+          cancel_stream_locked(exec_ctx, s, GRPC_ERROR_REF(error));
+          break;
+        }
+        GPR_ASSERT(error == GRPC_ERROR_NONE);
+        remaining -= GRPC_SLICE_LENGTH(message_slice);
+        grpc_slice_buffer_add(dest, message_slice);
+      } while (remaining != 0);
+      grpc_byte_stream_destroy(exec_ctx,
+                               op->payload->send_message.send_message);
+    }
+    if (error == GRPC_ERROR_NONE && op->send_trailing_metadata) {
+      grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md
+                                                  : &other->to_read_trailing_md;
+      bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled
+                                         : &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);
+        error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra trailing metadata");
+      } else {
+        if (!other->closed) {
+          fill_in_metadata(
+              exec_ctx, s,
+              op->payload->send_trailing_metadata.send_trailing_metadata, 0,
+              dest, NULL, destfilled);
+        }
+        s->trailing_md_sent = true;
+        if (!s->t->is_client && s->trailing_md_recvd &&
+            s->recv_trailing_md_op) {
+          INPROC_LOG(GPR_DEBUG,
+                     "perform_stream_op %p scheduling trailing-md-on-complete",
+                     s);
+          GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
+                             GRPC_ERROR_NONE);
+          s->recv_trailing_md_op = NULL;
+          needs_close = true;
+        }
+      }
+    }
+    if (other != NULL && other->reads_needed) {
+      if (!other->read_closure_scheduled) {
+        GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure, error);
+        other->read_closure_scheduled = true;
+      }
+      other->reads_needed = false;
+    }
+  }
+  if (error == GRPC_ERROR_NONE &&
+      (op->recv_initial_metadata || op->recv_message ||
+       op->recv_trailing_metadata)) {
+    // If there are any reads, mark it so that the read closure will react to
+    // them
+    if (op->recv_initial_metadata) {
+      s->recv_initial_md_op = op;
+    }
+    if (op->recv_message) {
+      s->recv_message_op = op;
+    }
+    if (op->recv_trailing_metadata) {
+      s->recv_trailing_md_op = op;
+    }
+
+    // We want to initiate the closure if:
+    // 1. There is initial metadata and something ready to take that
+    // 2. There is a message and something ready to take it
+    // 3. There is trailing metadata, even if nothing specifically wants
+    //    that because that can shut down the message as well
+    if ((s->to_read_initial_md_filled && op->recv_initial_metadata) ||
+        ((!slice_buffer_list_empty(&s->to_read_message) ||
+          s->trailing_md_recvd) &&
+         op->recv_message) ||
+        (s->to_read_trailing_md_filled)) {
+      if (!s->read_closure_scheduled) {
+        GRPC_CLOSURE_SCHED(exec_ctx, &s->read_closure, GRPC_ERROR_NONE);
+        s->read_closure_scheduled = true;
+      }
+    } else {
+      s->reads_needed = true;
+    }
+  } else {
+    if (error != GRPC_ERROR_NONE) {
+      // Schedule op's read closures that we didn't push to read state machine
+      if (op->recv_initial_metadata) {
+        INPROC_LOG(
+            GPR_DEBUG,
+            "perform_stream_op error %p scheduling initial-metadata-ready %p",
+            s, error);
+        GRPC_CLOSURE_SCHED(
+            exec_ctx,
+            op->payload->recv_initial_metadata.recv_initial_metadata_ready,
+            GRPC_ERROR_REF(error));
+      }
+      if (op->recv_message) {
+        INPROC_LOG(
+            GPR_DEBUG,
+            "perform_stream_op error %p scheduling recv message-ready %p", s,
+            error);
+        GRPC_CLOSURE_SCHED(exec_ctx,
+                           op->payload->recv_message.recv_message_ready,
+                           GRPC_ERROR_REF(error));
+      }
+    }
+    INPROC_LOG(GPR_DEBUG, "perform_stream_op %p scheduling on_complete %p", s,
+               error);
+    GRPC_CLOSURE_SCHED(exec_ctx, on_complete, GRPC_ERROR_REF(error));
+  }
+  if (needs_close) {
+    close_other_side_locked(exec_ctx, s, "perform_stream_op:other_side");
+    close_stream_locked(exec_ctx, s);
+  }
+  gpr_mu_unlock(mu);
+  GRPC_ERROR_UNREF(error);
+}
+
+static void close_transport_locked(grpc_exec_ctx *exec_ctx,
+                                   inproc_transport *t) {
+  INPROC_LOG(GPR_DEBUG, "close_transport %p %d", t, t->is_closed);
+  grpc_connectivity_state_set(
+      exec_ctx, &t->connectivity, GRPC_CHANNEL_SHUTDOWN,
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Closing transport."),
+      "close transport");
+  if (!t->is_closed) {
+    t->is_closed = true;
+    /* Also end all streams on this transport */
+    while (t->stream_list != NULL) {
+      // cancel_stream_locked also adjusts stream list
+      cancel_stream_locked(
+          exec_ctx, t->stream_list,
+          grpc_error_set_int(
+              GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed"),
+              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
+    }
+  }
+}
+
+static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                                 grpc_transport_op *op) {
+  inproc_transport *t = (inproc_transport *)gt;
+  INPROC_LOG(GPR_DEBUG, "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(
+        exec_ctx, &t->connectivity, op->connectivity_state,
+        op->on_connectivity_state_change);
+  }
+  if (op->set_accept_stream) {
+    t->accept_stream_cb = op->set_accept_stream_fn;
+    t->accept_stream_data = op->set_accept_stream_user_data;
+  }
+  if (op->on_consumed) {
+    GRPC_CLOSURE_SCHED(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
+  }
+
+  bool do_close = false;
+  if (op->goaway_error != GRPC_ERROR_NONE) {
+    do_close = true;
+    GRPC_ERROR_UNREF(op->goaway_error);
+  }
+  if (op->disconnect_with_error != GRPC_ERROR_NONE) {
+    do_close = true;
+    GRPC_ERROR_UNREF(op->disconnect_with_error);
+  }
+
+  if (do_close) {
+    close_transport_locked(exec_ctx, t);
+  }
+  gpr_mu_unlock(&t->mu->mu);
+}
+
+static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                           grpc_stream *gs,
+                           grpc_closure *then_schedule_closure) {
+  INPROC_LOG(GPR_DEBUG, "destroy_stream %p %p", gs, then_schedule_closure);
+  inproc_stream *s = (inproc_stream *)gs;
+  s->closure_at_destroy = then_schedule_closure;
+  really_destroy_stream(exec_ctx, s);
+}
+
+static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
+  inproc_transport *t = (inproc_transport *)gt;
+  INPROC_LOG(GPR_DEBUG, "destroy_transport %p", t);
+  gpr_mu_lock(&t->mu->mu);
+  close_transport_locked(exec_ctx, t);
+  gpr_mu_unlock(&t->mu->mu);
+  unref_transport(exec_ctx, t->other_side);
+  unref_transport(exec_ctx, t);
+}
+
+/*******************************************************************************
+ * Main inproc transport functions
+ */
+static void inproc_transports_create(grpc_exec_ctx *exec_ctx,
+                                     grpc_transport **server_transport,
+                                     const grpc_channel_args *server_args,
+                                     grpc_transport **client_transport,
+                                     const grpc_channel_args *client_args) {
+  INPROC_LOG(GPR_DEBUG, "inproc_transports_create");
+  inproc_transport *st = gpr_zalloc(sizeof(*st));
+  inproc_transport *ct = gpr_zalloc(sizeof(*ct));
+  // Share one lock between both sides since both sides get affected
+  st->mu = ct->mu = gpr_malloc(sizeof(*st->mu));
+  gpr_mu_init(&st->mu->mu);
+  gpr_ref_init(&st->mu->refs, 2);
+  st->base.vtable = &inproc_vtable;
+  ct->base.vtable = &inproc_vtable;
+  // Start each side of transport with 2 refs since they each have a ref
+  // to the other
+  gpr_ref_init(&st->refs, 2);
+  gpr_ref_init(&ct->refs, 2);
+  st->is_client = false;
+  ct->is_client = true;
+  grpc_connectivity_state_init(&st->connectivity, GRPC_CHANNEL_READY,
+                               "inproc_server");
+  grpc_connectivity_state_init(&ct->connectivity, GRPC_CHANNEL_READY,
+                               "inproc_client");
+  st->other_side = ct;
+  ct->other_side = st;
+  st->stream_list = NULL;
+  ct->stream_list = NULL;
+  *server_transport = (grpc_transport *)st;
+  *client_transport = (grpc_transport *)ct;
+}
+
+grpc_channel *grpc_inproc_channel_create(grpc_server *server,
+                                         grpc_channel_args *args,
+                                         void *reserved) {
+  GRPC_API_TRACE("grpc_inproc_channel_create(server=%p, args=%p)", 2,
+                 (server, args));
+
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  const grpc_channel_args *server_args = grpc_server_get_channel_args(server);
+
+  // Add a default authority channel argument for the client
+
+  grpc_arg default_authority_arg;
+  default_authority_arg.type = GRPC_ARG_STRING;
+  default_authority_arg.key = GRPC_ARG_DEFAULT_AUTHORITY;
+  default_authority_arg.value.string = "inproc.authority";
+  grpc_channel_args *client_args =
+      grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);
+
+  grpc_transport *server_transport;
+  grpc_transport *client_transport;
+  inproc_transports_create(&exec_ctx, &server_transport, server_args,
+                           &client_transport, client_args);
+
+  grpc_server_setup_transport(&exec_ctx, server, server_transport, NULL,
+                              server_args);
+  grpc_channel *channel =
+      grpc_channel_create(&exec_ctx, "inproc", client_args,
+                          GRPC_CLIENT_DIRECT_CHANNEL, client_transport);
+
+  // Free up created channel args
+  grpc_channel_args_destroy(&exec_ctx, client_args);
+
+  // Now finish scheduled operations
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  return channel;
+}
+
+/*******************************************************************************
+ * INTEGRATION GLUE
+ */
+
+static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                        grpc_stream *gs, grpc_pollset *pollset) {
+  // Nothing to do here
+}
+
+static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                            grpc_stream *gs, grpc_pollset_set *pollset_set) {
+  // Nothing to do here
+}
+
+static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
+  return gpr_strdup("inproc");
+}
+
+static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
+  return NULL;
+}
+
+static const grpc_transport_vtable inproc_vtable = {
+    sizeof(inproc_stream), "inproc",
+    init_stream,           set_pollset,
+    set_pollset_set,       perform_stream_op,
+    perform_transport_op,  destroy_stream,
+    destroy_transport,     get_peer,
+    get_endpoint};
+
+/*******************************************************************************
+ * GLOBAL INIT AND DESTROY
+ */
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+
+void grpc_inproc_transport_init(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL,
+                    grpc_schedule_on_exec_ctx);
+  g_empty_slice = grpc_slice_from_static_buffer(NULL, 0);
+
+  grpc_slice key_tmp = grpc_slice_from_static_string(":path");
+  g_fake_path_key = grpc_slice_intern(key_tmp);
+  grpc_slice_unref_internal(&exec_ctx, key_tmp);
+
+  g_fake_path_value = grpc_slice_from_static_string("/");
+
+  grpc_slice auth_tmp = grpc_slice_from_static_string(":authority");
+  g_fake_auth_key = grpc_slice_intern(auth_tmp);
+  grpc_slice_unref_internal(&exec_ctx, auth_tmp);
+
+  g_fake_auth_value = grpc_slice_from_static_string("inproc-fail");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void grpc_inproc_transport_shutdown(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_slice_unref_internal(&exec_ctx, g_empty_slice);
+  grpc_slice_unref_internal(&exec_ctx, g_fake_path_key);
+  grpc_slice_unref_internal(&exec_ctx, g_fake_path_value);
+  grpc_slice_unref_internal(&exec_ctx, g_fake_auth_key);
+  grpc_slice_unref_internal(&exec_ctx, g_fake_auth_value);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
diff --git a/src/core/ext/transport/inproc/inproc_transport.h b/src/core/ext/transport/inproc/inproc_transport.h
new file mode 100644
index 0000000..37e6d99
--- /dev/null
+++ b/src/core/ext/transport/inproc/inproc_transport.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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_EXT_TRANSPORT_INPROC_INPROC_TRANSPORT_H
+#define GRPC_CORE_EXT_TRANSPORT_INPROC_INPROC_TRANSPORT_H
+
+#include "src/core/lib/transport/transport_impl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+grpc_channel *grpc_inproc_channel_create(grpc_server *server,
+                                         grpc_channel_args *args,
+                                         void *reserved);
+
+extern grpc_tracer_flag grpc_inproc_trace;
+
+void grpc_inproc_transport_init(void);
+void grpc_inproc_transport_shutdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_INPROC_INPROC_TRANSPORT_H */
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index 1066664..0f8e33c 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-grpc_tracer_flag grpc_trace_channel = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_channel = GRPC_TRACER_INITIALIZER(false, "channel");
 
 /* Memory layouts.
 
diff --git a/src/core/lib/channel/channel_stack_builder.c b/src/core/lib/channel/channel_stack_builder.c
index 01529df..c369e33 100644
--- a/src/core/lib/channel/channel_stack_builder.c
+++ b/src/core/lib/channel/channel_stack_builder.c
@@ -24,7 +24,7 @@
 #include <grpc/support/string_util.h>
 
 grpc_tracer_flag grpc_trace_channel_stack_builder =
-    GRPC_TRACER_INITIALIZER(false);
+    GRPC_TRACER_INITIALIZER(false, "channel_stack_builder");
 
 typedef struct filter_node {
   struct filter_node *next;
diff --git a/src/core/lib/compression/stream_compression.c b/src/core/lib/compression/stream_compression.c
new file mode 100644
index 0000000..df13d53
--- /dev/null
+++ b/src/core/lib/compression/stream_compression.c
@@ -0,0 +1,191 @@
+/*
+ *
+ * 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/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/compression/stream_compression.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice_internal.h"
+
+#define OUTPUT_BLOCK_SIZE (1024)
+
+static bool gzip_flate(grpc_stream_compression_context *ctx,
+                       grpc_slice_buffer *in, grpc_slice_buffer *out,
+                       size_t *output_size, size_t max_output_size, int flush,
+                       bool *end_of_context) {
+  GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH);
+  /* Full flush is not allowed when inflating. */
+  GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH)));
+
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  int r;
+  bool eoc = false;
+  size_t original_max_output_size = max_output_size;
+  while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) {
+    size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size
+                                                            : OUTPUT_BLOCK_SIZE;
+    grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size);
+    ctx->zs.avail_out = (uInt)slice_size;
+    ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out);
+    while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) {
+      grpc_slice slice = grpc_slice_buffer_take_first(in);
+      ctx->zs.avail_in = (uInt)GRPC_SLICE_LENGTH(slice);
+      ctx->zs.next_in = GRPC_SLICE_START_PTR(slice);
+      r = ctx->flate(&ctx->zs, Z_NO_FLUSH);
+      if (r < 0 && r != Z_BUF_ERROR) {
+        gpr_log(GPR_ERROR, "zlib error (%d)", r);
+        grpc_slice_unref_internal(&exec_ctx, slice_out);
+        grpc_exec_ctx_finish(&exec_ctx);
+        return false;
+      } else if (r == Z_STREAM_END && ctx->flate == inflate) {
+        eoc = true;
+      }
+      if (ctx->zs.avail_in > 0) {
+        grpc_slice_buffer_undo_take_first(
+            in,
+            grpc_slice_sub(slice, GRPC_SLICE_LENGTH(slice) - ctx->zs.avail_in,
+                           GRPC_SLICE_LENGTH(slice)));
+      }
+      grpc_slice_unref_internal(&exec_ctx, slice);
+    }
+    if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) {
+      GPR_ASSERT(in->length == 0);
+      r = ctx->flate(&ctx->zs, flush);
+      if (flush == Z_SYNC_FLUSH) {
+        switch (r) {
+          case Z_OK:
+            /* Maybe flush is not complete; just made some partial progress. */
+            if (ctx->zs.avail_out > 0) {
+              flush = 0;
+            }
+            break;
+          case Z_BUF_ERROR:
+          case Z_STREAM_END:
+            flush = 0;
+            break;
+          default:
+            gpr_log(GPR_ERROR, "zlib error (%d)", r);
+            grpc_slice_unref_internal(&exec_ctx, slice_out);
+            grpc_exec_ctx_finish(&exec_ctx);
+            return false;
+        }
+      } else if (flush == Z_FINISH) {
+        switch (r) {
+          case Z_OK:
+          case Z_BUF_ERROR:
+            /* Wait for the next loop to assign additional output space. */
+            GPR_ASSERT(ctx->zs.avail_out == 0);
+            break;
+          case Z_STREAM_END:
+            flush = 0;
+            break;
+          default:
+            gpr_log(GPR_ERROR, "zlib error (%d)", r);
+            grpc_slice_unref_internal(&exec_ctx, slice_out);
+            grpc_exec_ctx_finish(&exec_ctx);
+            return false;
+        }
+      }
+    }
+
+    if (ctx->zs.avail_out == 0) {
+      grpc_slice_buffer_add(out, slice_out);
+    } else if (ctx->zs.avail_out < slice_size) {
+      slice_out.data.refcounted.length -= ctx->zs.avail_out;
+      grpc_slice_buffer_add(out, slice_out);
+    } else {
+      grpc_slice_unref_internal(&exec_ctx, slice_out);
+    }
+    max_output_size -= (slice_size - ctx->zs.avail_out);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  if (end_of_context) {
+    *end_of_context = eoc;
+  }
+  if (output_size) {
+    *output_size = original_max_output_size - max_output_size;
+  }
+  return true;
+}
+
+bool grpc_stream_compress(grpc_stream_compression_context *ctx,
+                          grpc_slice_buffer *in, grpc_slice_buffer *out,
+                          size_t *output_size, size_t max_output_size,
+                          grpc_stream_compression_flush flush) {
+  GPR_ASSERT(ctx->flate == deflate);
+  int gzip_flush;
+  switch (flush) {
+    case GRPC_STREAM_COMPRESSION_FLUSH_NONE:
+      gzip_flush = 0;
+      break;
+    case GRPC_STREAM_COMPRESSION_FLUSH_SYNC:
+      gzip_flush = Z_SYNC_FLUSH;
+      break;
+    case GRPC_STREAM_COMPRESSION_FLUSH_FINISH:
+      gzip_flush = Z_FINISH;
+      break;
+    default:
+      gzip_flush = 0;
+  }
+  return gzip_flate(ctx, in, out, output_size, max_output_size, gzip_flush,
+                    NULL);
+}
+
+bool grpc_stream_decompress(grpc_stream_compression_context *ctx,
+                            grpc_slice_buffer *in, grpc_slice_buffer *out,
+                            size_t *output_size, size_t max_output_size,
+                            bool *end_of_context) {
+  GPR_ASSERT(ctx->flate == inflate);
+  return gzip_flate(ctx, in, out, output_size, max_output_size, Z_SYNC_FLUSH,
+                    end_of_context);
+}
+
+grpc_stream_compression_context *grpc_stream_compression_context_create(
+    grpc_stream_compression_method method) {
+  grpc_stream_compression_context *ctx =
+      gpr_zalloc(sizeof(grpc_stream_compression_context));
+  int r;
+  if (ctx == NULL) {
+    return NULL;
+  }
+  if (method == GRPC_STREAM_COMPRESSION_DECOMPRESS) {
+    r = inflateInit2(&ctx->zs, 0x1F);
+    ctx->flate = inflate;
+  } else {
+    r = deflateInit2(&ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8,
+                     Z_DEFAULT_STRATEGY);
+    ctx->flate = deflate;
+  }
+  if (r != Z_OK) {
+    gpr_free(ctx);
+    return NULL;
+  }
+
+  return ctx;
+}
+
+void grpc_stream_compression_context_destroy(
+    grpc_stream_compression_context *ctx) {
+  if (ctx->flate == inflate) {
+    inflateEnd(&ctx->zs);
+  } else {
+    deflateEnd(&ctx->zs);
+  }
+  gpr_free(ctx);
+}
diff --git a/src/core/lib/compression/stream_compression.h b/src/core/lib/compression/stream_compression.h
new file mode 100644
index 0000000..844dff8
--- /dev/null
+++ b/src/core/lib/compression/stream_compression.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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_LIB_COMPRESSION_STREAM_COMPRESSION_H
+#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_H
+
+#include <stdbool.h>
+
+#include <grpc/slice_buffer.h>
+#include <zlib.h>
+
+/* Stream compression/decompression context */
+typedef struct grpc_stream_compression_context {
+  z_stream zs;
+  int (*flate)(z_stream *zs, int flush);
+} grpc_stream_compression_context;
+
+typedef enum grpc_stream_compression_method {
+  GRPC_STREAM_COMPRESSION_COMPRESS = 0,
+  GRPC_STREAM_COMPRESSION_DECOMPRESS,
+  GRPC_STREAM_COMPRESSION_METHOD_COUNT
+} grpc_stream_compression_method;
+
+typedef enum grpc_stream_compression_flush {
+  GRPC_STREAM_COMPRESSION_FLUSH_NONE = 0,
+  GRPC_STREAM_COMPRESSION_FLUSH_SYNC,
+  GRPC_STREAM_COMPRESSION_FLUSH_FINISH,
+  GRPC_STREAM_COMPRESSION_FLUSH_COUNT
+} grpc_stream_compression_flush;
+
+/**
+ * Compress bytes provided in \a in with a given context, with an optional flush
+ * at the end of compression. Emits at most \a max_output_size compressed bytes
+ * into \a out. If all the bytes in input buffer \a in are depleted and \a flush
+ * is not GRPC_STREAM_COMPRESSION_FLUSH_NONE, the corresponding flush method is
+ * executed. The total number of bytes emitted is outputed in \a output_size.
+ *
+ * A SYNC flush indicates that the entire messages in \a in can be decompressed
+ * from \a out. A FINISH flush implies a SYNC flush, and that any further
+ * compression will not be dependent on the state of the current context and any
+ * previous compressed bytes. It allows corresponding decompression context to
+ * be dropped when reaching this boundary.
+ */
+bool grpc_stream_compress(grpc_stream_compression_context *ctx,
+                          grpc_slice_buffer *in, grpc_slice_buffer *out,
+                          size_t *output_size, size_t max_output_size,
+                          grpc_stream_compression_flush flush);
+
+/**
+ * Decompress bytes provided in \a in with a given context. Emits at most \a
+ * max_output_size decompressed bytes into \a out. If decompression process
+ * reached the end of a gzip stream, \a end_of_context is set to true; otherwise
+ * it is set to false. The total number of bytes emitted is outputed in \a
+ * output_size.
+ */
+bool grpc_stream_decompress(grpc_stream_compression_context *ctx,
+                            grpc_slice_buffer *in, grpc_slice_buffer *out,
+                            size_t *output_size, size_t max_output_size,
+                            bool *end_of_context);
+
+/**
+ * Creates a stream compression context. \a pending_bytes_buffer is the input
+ * buffer for compression/decompression operations. \a method specifies whether
+ * the context is for compression or decompression.
+ */
+grpc_stream_compression_context *grpc_stream_compression_context_create(
+    grpc_stream_compression_method method);
+
+/**
+ * Destroys a stream compression context.
+ */
+void grpc_stream_compression_context_destroy(
+    grpc_stream_compression_context *ctx);
+
+#endif
diff --git a/src/core/lib/debug/trace.c b/src/core/lib/debug/trace.c
index 8249b2e..c6c1853 100644
--- a/src/core/lib/debug/trace.c
+++ b/src/core/lib/debug/trace.c
@@ -27,7 +27,6 @@
 int grpc_tracer_set_enabled(const char *name, int enabled);
 
 typedef struct tracer {
-  const char *name;
   grpc_tracer_flag *flag;
   struct tracer *next;
 } tracer;
@@ -39,9 +38,8 @@
 #define TRACER_SET(flag, on) (flag).value = (on)
 #endif
 
-void grpc_register_tracer(const char *name, grpc_tracer_flag *flag) {
+void grpc_register_tracer(grpc_tracer_flag *flag) {
   tracer *t = gpr_malloc(sizeof(*t));
-  t->name = name;
   t->flag = flag;
   t->next = tracers;
   TRACER_SET(*flag, false);
@@ -93,6 +91,14 @@
   gpr_free(strings);
 }
 
+static void list_tracers() {
+  gpr_log(GPR_DEBUG, "available tracers:");
+  tracer *t;
+  for (t = tracers; t; t = t->next) {
+    gpr_log(GPR_DEBUG, "\t%s", t->flag->name);
+  }
+}
+
 void grpc_tracer_init(const char *env_var) {
   char *e = gpr_getenv(env_var);
   if (e != NULL) {
@@ -115,10 +121,18 @@
     for (t = tracers; t; t = t->next) {
       TRACER_SET(*t->flag, enabled);
     }
+  } else if (0 == strcmp(name, "list_tracers")) {
+    list_tracers();
+  } else if (0 == strcmp(name, "refcount")) {
+    for (t = tracers; t; t = t->next) {
+      if (strstr(t->flag->name, "refcount") != NULL) {
+        TRACER_SET(*t->flag, enabled);
+      }
+    }
   } else {
     int found = 0;
     for (t = tracers; t; t = t->next) {
-      if (0 == strcmp(name, t->name)) {
+      if (0 == strcmp(name, t->flag->name)) {
         TRACER_SET(*t->flag, enabled);
         found = 1;
       }
diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h
index 7cc9fb4..dd9e6a3 100644
--- a/src/core/lib/debug/trace.h
+++ b/src/core/lib/debug/trace.h
@@ -35,19 +35,20 @@
 #else
   bool value;
 #endif
+  char *name;
 } grpc_tracer_flag;
 
 #ifdef GRPC_THREADSAFE_TRACER
 #define GRPC_TRACER_ON(flag) (gpr_atm_no_barrier_load(&(flag).value) != 0)
-#define GRPC_TRACER_INITIALIZER(on) \
-  { (gpr_atm)(on) }
+#define GRPC_TRACER_INITIALIZER(on, name) \
+  { (gpr_atm)(on), (name) }
 #else
 #define GRPC_TRACER_ON(flag) ((flag).value)
-#define GRPC_TRACER_INITIALIZER(on) \
-  { (on) }
+#define GRPC_TRACER_INITIALIZER(on, name) \
+  { (on), (name) }
 #endif
 
-void grpc_register_tracer(const char *name, grpc_tracer_flag *flag);
+void grpc_register_tracer(grpc_tracer_flag *flag);
 void grpc_tracer_init(const char *env_var_name);
 void grpc_tracer_shutdown(void);
 
diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c
index 71d697c..9c5e93f 100644
--- a/src/core/lib/http/parser.c
+++ b/src/core/lib/http/parser.c
@@ -25,7 +25,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-grpc_tracer_flag grpc_http1_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_http1_trace = GRPC_TRACER_INITIALIZER(false, "http1");
 
 static char *buf2str(void *buffer, size_t length) {
   char *out = gpr_malloc(length + 1);
diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c
index e028e72..26f9cbe 100644
--- a/src/core/lib/iomgr/closure.c
+++ b/src/core/lib/iomgr/closure.c
@@ -25,7 +25,7 @@
 #include "src/core/lib/profiling/timers.h"
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_closure = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_closure = GRPC_TRACER_INITIALIZER(false, "closure");
 #endif
 
 #ifndef NDEBUG
diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c
index 7f9c5d8..9b66987 100644
--- a/src/core/lib/iomgr/combiner.c
+++ b/src/core/lib/iomgr/combiner.c
@@ -27,7 +27,8 @@
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/profiling/timers.h"
 
-grpc_tracer_flag grpc_combiner_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_combiner_trace =
+    GRPC_TRACER_INITIALIZER(false, "combiner");
 
 #define GRPC_COMBINER_TRACE(fn)                \
   do {                                         \
@@ -72,10 +73,8 @@
 static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
 
 grpc_combiner *grpc_combiner_create(void) {
-  grpc_combiner *lock = gpr_malloc(sizeof(*lock));
+  grpc_combiner *lock = gpr_zalloc(sizeof(*lock));
   gpr_ref_init(&lock->refs, 1);
-  lock->next_combiner_on_this_exec_ctx = NULL;
-  lock->time_to_execute_final_list = false;
   lock->scheduler.vtable = &scheduler;
   lock->finally_scheduler.vtable = &finally_scheduler;
   gpr_atm_no_barrier_store(&lock->state, STATE_UNORPHANED);
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
index a95929a..3759dda 100644
--- a/src/core/lib/iomgr/error.c
+++ b/src/core/lib/iomgr/error.c
@@ -36,7 +36,8 @@
 #include "src/core/lib/slice/slice_internal.h"
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_error_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_error_refcount =
+    GRPC_TRACER_INITIALIZER(false, "error_refcount");
 #endif
 
 static const char *error_int_name(grpc_error_ints key) {
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.c b/src/core/lib/iomgr/ev_epoll1_linux.c
index 66ba601..dc48d73 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.c
+++ b/src/core/lib/iomgr/ev_epoll1_linux.c
@@ -45,6 +45,7 @@
 #include "src/core/lib/iomgr/wakeup_fd_posix.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/support/block_annotate.h"
+#include "src/core/lib/support/string.h"
 
 static grpc_wakeup_fd global_wakeup_fd;
 static int g_epfd;
@@ -77,8 +78,21 @@
 
 typedef enum { UNKICKED, KICKED, DESIGNATED_POLLER } kick_state;
 
+static const char *kick_state_string(kick_state st) {
+  switch (st) {
+    case UNKICKED:
+      return "UNKICKED";
+    case KICKED:
+      return "KICKED";
+    case DESIGNATED_POLLER:
+      return "DESIGNATED_POLLER";
+  }
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
+}
+
 struct grpc_pollset_worker {
   kick_state kick_state;
+  int kick_state_mutator;  // which line of code last changed kick state
   bool initialized_cv;
   grpc_pollset_worker *next;
   grpc_pollset_worker *prev;
@@ -86,6 +100,12 @@
   grpc_closure_list schedule_on_end_work;
 };
 
+#define SET_KICK_STATE(worker, state)        \
+  do {                                       \
+    (worker)->kick_state = (state);          \
+    (worker)->kick_state_mutator = __LINE__; \
+  } while (false)
+
 #define MAX_NEIGHBOURHOODS 1024
 
 typedef struct pollset_neighbourhood {
@@ -100,10 +120,15 @@
   bool reassigning_neighbourhood;
   grpc_pollset_worker *root_worker;
   bool kicked_without_poller;
+
+  /* Set to true if the pollset is observed to have no workers available to
+   * poll */
   bool seen_inactive;
-  bool shutting_down;          /* Is the pollset shutting down ? */
-  bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */
+  bool shutting_down;             /* Is the pollset shutting down ? */
   grpc_closure *shutdown_closure; /* Called after after shutdown is complete */
+
+  /* Number of workers who are *about-to* attach themselves to the pollset
+   * worker list */
   int begin_refs;
 
   grpc_pollset *next;
@@ -224,7 +249,7 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
+                      bool already_closed, const char *reason) {
   grpc_error *error = GRPC_ERROR_NONE;
 
   if (!grpc_lfev_is_shutdown(&fd->read_closure)) {
@@ -235,7 +260,7 @@
      descriptor fd->fd (but we still own the grpc_fd structure). */
   if (release_fd != NULL) {
     *release_fd = fd->fd;
-  } else {
+  } else if (!already_closed) {
     close(fd->fd);
   }
 
@@ -263,29 +288,23 @@
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read");
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write");
 }
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_pollset *notifier) {
-  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
-
-  /* Note, it is possible that fd_become_readable might be called twice with
-     different 'notifier's when an fd becomes readable and it is in two epoll
-     sets (This can happen briefly during polling island merges). In such cases
-     it does not really matter which notifer is set as the read_notifier_pollset
-     (They would both point to the same polling island anyway) */
+  grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read");
   /* Use release store to match with acquire load in fd_get_read_notifier */
   gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
 /*******************************************************************************
@@ -410,18 +429,28 @@
   if (pollset->root_worker != NULL) {
     grpc_pollset_worker *worker = pollset->root_worker;
     do {
-      if (worker->initialized_cv) {
-        worker->kick_state = KICKED;
-        gpr_cv_signal(&worker->cv);
-      } else {
-        worker->kick_state = KICKED;
-        append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd),
-                     "pollset_shutdown");
+      switch (worker->kick_state) {
+        case KICKED:
+          break;
+        case UNKICKED:
+          SET_KICK_STATE(worker, KICKED);
+          if (worker->initialized_cv) {
+            gpr_cv_signal(&worker->cv);
+          }
+          break;
+        case DESIGNATED_POLLER:
+          SET_KICK_STATE(worker, KICKED);
+          append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd),
+                       "pollset_kick_all");
+          break;
       }
 
       worker = worker->next;
     } while (worker != pollset->root_worker);
   }
+  // TODO: sreek.  Check if we need to set 'kicked_without_poller' to true here
+  // in the else case
+
   return error;
 }
 
@@ -437,7 +466,9 @@
 static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                              grpc_closure *closure) {
   GPR_ASSERT(pollset->shutdown_closure == NULL);
+  GPR_ASSERT(!pollset->shutting_down);
   pollset->shutdown_closure = closure;
+  pollset->shutting_down = true;
   GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset));
   pollset_maybe_finish_shutdown(exec_ctx, pollset);
 }
@@ -510,10 +541,14 @@
                          gpr_timespec deadline) {
   if (worker_hdl != NULL) *worker_hdl = worker;
   worker->initialized_cv = false;
-  worker->kick_state = UNKICKED;
+  SET_KICK_STATE(worker, UNKICKED);
   worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
   pollset->begin_refs++;
 
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_ERROR, "PS:%p BEGIN_STARTS:%p", pollset, worker);
+  }
+
   if (pollset->seen_inactive) {
     // pollset has been observed to be inactive, we need to move back to the
     // active list
@@ -529,6 +564,11 @@
   retry_lock_neighbourhood:
     gpr_mu_lock(&neighbourhood->mu);
     gpr_mu_lock(&pollset->mu);
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, "PS:%p BEGIN_REORG:%p kick_state=%s is_reassigning=%d",
+              pollset, worker, kick_state_string(worker->kick_state),
+              is_reassigning);
+    }
     if (pollset->seen_inactive) {
       if (neighbourhood != pollset->neighbourhood) {
         gpr_mu_unlock(&neighbourhood->mu);
@@ -539,8 +579,14 @@
       pollset->seen_inactive = false;
       if (neighbourhood->active_root == NULL) {
         neighbourhood->active_root = pollset->next = pollset->prev = pollset;
-        if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
-          worker->kick_state = DESIGNATED_POLLER;
+        /* TODO: sreek. Why would this worker state be other than UNKICKED
+         * here ? (since the worker isn't added to the pollset yet, there is no
+         * way it can be "found" by other threads to get kicked). */
+
+        /* If there is no designated poller, make this the designated poller */
+        if (worker->kick_state == UNKICKED &&
+            gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
+          SET_KICK_STATE(worker, DESIGNATED_POLLER);
         }
       } else {
         pollset->next = neighbourhood->active_root;
@@ -554,24 +600,53 @@
     }
     gpr_mu_unlock(&neighbourhood->mu);
   }
+
   worker_insert(pollset, worker);
   pollset->begin_refs--;
-  if (worker->kick_state == UNKICKED) {
+  if (worker->kick_state == UNKICKED && !pollset->kicked_without_poller) {
     GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
     worker->initialized_cv = true;
     gpr_cv_init(&worker->cv);
-    while (worker->kick_state == UNKICKED &&
-           pollset->shutdown_closure == NULL) {
+    while (worker->kick_state == UNKICKED && !pollset->shutting_down) {
+      if (GRPC_TRACER_ON(grpc_polling_trace)) {
+        gpr_log(GPR_ERROR, "PS:%p BEGIN_WAIT:%p kick_state=%s shutdown=%d",
+                pollset, worker, kick_state_string(worker->kick_state),
+                pollset->shutting_down);
+      }
+
       if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) &&
           worker->kick_state == UNKICKED) {
-        worker->kick_state = KICKED;
+        /* If gpr_cv_wait returns true (i.e a timeout), pretend that the worker
+           received a kick */
+        SET_KICK_STATE(worker, KICKED);
       }
     }
     *now = gpr_now(now->clock_type);
   }
 
-  return worker->kick_state == DESIGNATED_POLLER &&
-         pollset->shutdown_closure == NULL;
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_ERROR,
+            "PS:%p BEGIN_DONE:%p kick_state=%s shutdown=%d "
+            "kicked_without_poller: %d",
+            pollset, worker, kick_state_string(worker->kick_state),
+            pollset->shutting_down, pollset->kicked_without_poller);
+  }
+
+  /* We release pollset lock in this function at a couple of places:
+   *   1. Briefly when assigning pollset to a neighbourhood
+   *   2. When doing gpr_cv_wait()
+   * It is possible that 'kicked_without_poller' was set to true during (1) and
+   * 'shutting_down' is set to true during (1) or (2). If either of them is
+   * true, this worker cannot do polling */
+  /* TODO(sreek): Perhaps there is a better way to handle kicked_without_poller
+   * case; especially when the worker is the DESIGNATED_POLLER */
+
+  if (pollset->kicked_without_poller) {
+    pollset->kicked_without_poller = false;
+    return false;
+  }
+
+  return worker->kick_state == DESIGNATED_POLLER && !pollset->shutting_down;
 }
 
 static bool check_neighbourhood_for_available_poller(
@@ -591,10 +666,18 @@
           case UNKICKED:
             if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
                                        (gpr_atm)inspect_worker)) {
-              inspect_worker->kick_state = DESIGNATED_POLLER;
+              if (GRPC_TRACER_ON(grpc_polling_trace)) {
+                gpr_log(GPR_DEBUG, " .. choose next poller to be %p",
+                        inspect_worker);
+              }
+              SET_KICK_STATE(inspect_worker, DESIGNATED_POLLER);
               if (inspect_worker->initialized_cv) {
                 gpr_cv_signal(&inspect_worker->cv);
               }
+            } else {
+              if (GRPC_TRACER_ON(grpc_polling_trace)) {
+                gpr_log(GPR_DEBUG, " .. beaten to choose next poller");
+              }
             }
             // even if we didn't win the cas, there's a worker, we can stop
             found_worker = true;
@@ -607,9 +690,12 @@
             break;
         }
         inspect_worker = inspect_worker->next;
-      } while (inspect_worker != inspect->root_worker);
+      } while (!found_worker && inspect_worker != inspect->root_worker);
     }
     if (!found_worker) {
+      if (GRPC_TRACER_ON(grpc_polling_trace)) {
+        gpr_log(GPR_DEBUG, " .. mark pollset %p inactive", inspect);
+      }
       inspect->seen_inactive = true;
       if (inspect == neighbourhood->active_root) {
         neighbourhood->active_root =
@@ -627,15 +713,22 @@
 static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                        grpc_pollset_worker *worker,
                        grpc_pollset_worker **worker_hdl) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PS:%p END_WORKER:%p", pollset, worker);
+  }
   if (worker_hdl != NULL) *worker_hdl = NULL;
-  worker->kick_state = KICKED;
+  /* Make sure we appear kicked */
+  SET_KICK_STATE(worker, KICKED);
   grpc_closure_list_move(&worker->schedule_on_end_work,
                          &exec_ctx->closure_list);
   if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
     if (worker->next != worker && worker->next->kick_state == UNKICKED) {
+      if (GRPC_TRACER_ON(grpc_polling_trace)) {
+        gpr_log(GPR_DEBUG, " .. 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);
-      worker->next->kick_state = DESIGNATED_POLLER;
+      SET_KICK_STATE(worker->next, DESIGNATED_POLLER);
       gpr_cv_signal(&worker->next->cv);
       if (grpc_exec_ctx_has_work(exec_ctx)) {
         gpr_mu_unlock(&pollset->mu);
@@ -644,9 +737,9 @@
       }
     } else {
       gpr_atm_no_barrier_store(&g_active_poller, 0);
-      gpr_mu_unlock(&pollset->mu);
       size_t poller_neighbourhood_idx =
           (size_t)(pollset->neighbourhood - g_neighbourhoods);
+      gpr_mu_unlock(&pollset->mu);
       bool found_worker = false;
       bool scan_state[MAX_NEIGHBOURHOODS];
       for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
@@ -682,6 +775,9 @@
   if (worker->initialized_cv) {
     gpr_cv_destroy(&worker->cv);
   }
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, " .. remove worker");
+  }
   if (EMPTIED == worker_remove(pollset, worker)) {
     pollset_maybe_finish_shutdown(exec_ctx, pollset);
   }
@@ -702,16 +798,18 @@
     pollset->kicked_without_poller = false;
     return GRPC_ERROR_NONE;
   }
-  gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
   if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
+    gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
     gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
-    GPR_ASSERT(!pollset->shutdown_closure);
+    GPR_ASSERT(!pollset->shutting_down);
     GPR_ASSERT(!pollset->seen_inactive);
     gpr_mu_unlock(&pollset->mu);
     append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline),
                  err_desc);
     gpr_mu_lock(&pollset->mu);
     gpr_tls_set(&g_current_thread_worker, 0);
+  } else {
+    gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
   }
   end_worker(exec_ctx, pollset, &worker, worker_hdl);
   gpr_tls_set(&g_current_thread_pollset, 0);
@@ -720,46 +818,136 @@
 
 static grpc_error *pollset_kick(grpc_pollset *pollset,
                                 grpc_pollset_worker *specific_worker) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_strvec log;
+    gpr_strvec_init(&log);
+    char *tmp;
+    gpr_asprintf(
+        &tmp, "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset,
+        specific_worker, (void *)gpr_tls_get(&g_current_thread_pollset),
+        (void *)gpr_tls_get(&g_current_thread_worker), pollset->root_worker);
+    gpr_strvec_add(&log, tmp);
+    if (pollset->root_worker != NULL) {
+      gpr_asprintf(&tmp, " {kick_state=%s next=%p {kick_state=%s}}",
+                   kick_state_string(pollset->root_worker->kick_state),
+                   pollset->root_worker->next,
+                   kick_state_string(pollset->root_worker->next->kick_state));
+      gpr_strvec_add(&log, tmp);
+    }
+    if (specific_worker != NULL) {
+      gpr_asprintf(&tmp, " worker_kick_state=%s",
+                   kick_state_string(specific_worker->kick_state));
+      gpr_strvec_add(&log, tmp);
+    }
+    tmp = gpr_strvec_flatten(&log, NULL);
+    gpr_strvec_destroy(&log);
+    gpr_log(GPR_ERROR, "%s", tmp);
+    gpr_free(tmp);
+  }
   if (specific_worker == NULL) {
     if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
       grpc_pollset_worker *root_worker = pollset->root_worker;
       if (root_worker == NULL) {
         pollset->kicked_without_poller = true;
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_ERROR, " .. kicked_without_poller");
+        }
         return GRPC_ERROR_NONE;
       }
       grpc_pollset_worker *next_worker = root_worker->next;
-      if (root_worker == next_worker &&
-          root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
-                             &g_active_poller)) {
-        root_worker->kick_state = KICKED;
+      if (root_worker->kick_state == KICKED) {
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_ERROR, " .. already kicked %p", root_worker);
+        }
+        SET_KICK_STATE(root_worker, KICKED);
+        return GRPC_ERROR_NONE;
+      } else if (next_worker->kick_state == KICKED) {
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_ERROR, " .. already kicked %p", next_worker);
+        }
+        SET_KICK_STATE(next_worker, KICKED);
+        return GRPC_ERROR_NONE;
+      } else if (root_worker ==
+                     next_worker &&  // only try and wake up a poller if
+                                     // there is no next worker
+                 root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
+                                    &g_active_poller)) {
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_ERROR, " .. kicked %p", root_worker);
+        }
+        SET_KICK_STATE(root_worker, KICKED);
         return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
       } else if (next_worker->kick_state == UNKICKED) {
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_ERROR, " .. kicked %p", next_worker);
+        }
         GPR_ASSERT(next_worker->initialized_cv);
-        next_worker->kick_state = KICKED;
+        SET_KICK_STATE(next_worker, KICKED);
         gpr_cv_signal(&next_worker->cv);
         return GRPC_ERROR_NONE;
+      } else if (next_worker->kick_state == DESIGNATED_POLLER) {
+        if (root_worker->kick_state != DESIGNATED_POLLER) {
+          if (GRPC_TRACER_ON(grpc_polling_trace)) {
+            gpr_log(
+                GPR_ERROR,
+                " .. kicked root non-poller %p (initialized_cv=%d) (poller=%p)",
+                root_worker, root_worker->initialized_cv, next_worker);
+          }
+          SET_KICK_STATE(root_worker, KICKED);
+          if (root_worker->initialized_cv) {
+            gpr_cv_signal(&root_worker->cv);
+          }
+          return GRPC_ERROR_NONE;
+        } else {
+          if (GRPC_TRACER_ON(grpc_polling_trace)) {
+            gpr_log(GPR_ERROR, " .. non-root poller %p (root=%p)", next_worker,
+                    root_worker);
+          }
+          SET_KICK_STATE(next_worker, KICKED);
+          return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
+        }
       } else {
+        GPR_ASSERT(next_worker->kick_state == KICKED);
+        SET_KICK_STATE(next_worker, KICKED);
         return GRPC_ERROR_NONE;
       }
     } else {
+      if (GRPC_TRACER_ON(grpc_polling_trace)) {
+        gpr_log(GPR_ERROR, " .. kicked while waking up");
+      }
       return GRPC_ERROR_NONE;
     }
   } else if (specific_worker->kick_state == KICKED) {
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, " .. specific worker already kicked");
+    }
     return GRPC_ERROR_NONE;
   } else if (gpr_tls_get(&g_current_thread_worker) ==
              (intptr_t)specific_worker) {
-    specific_worker->kick_state = KICKED;
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, " .. mark %p kicked", specific_worker);
+    }
+    SET_KICK_STATE(specific_worker, KICKED);
     return GRPC_ERROR_NONE;
   } else if (specific_worker ==
              (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
-    specific_worker->kick_state = KICKED;
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, " .. kick active poller");
+    }
+    SET_KICK_STATE(specific_worker, KICKED);
     return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
   } else if (specific_worker->initialized_cv) {
-    specific_worker->kick_state = KICKED;
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, " .. kick waiting worker");
+    }
+    SET_KICK_STATE(specific_worker, KICKED);
     gpr_cv_signal(&specific_worker->cv);
     return GRPC_ERROR_NONE;
   } else {
-    specific_worker->kick_state = KICKED;
+    if (GRPC_TRACER_ON(grpc_polling_trace)) {
+      gpr_log(GPR_ERROR, " .. kick non-waiting worker");
+    }
+    SET_KICK_STATE(specific_worker, KICKED);
     return GRPC_ERROR_NONE;
   }
 }
@@ -805,6 +993,7 @@
 static void shutdown_engine(void) {
   fd_global_shutdown();
   pollset_global_shutdown();
+  close(g_epfd);
 }
 
 static const grpc_event_engine_vtable vtable = {
@@ -841,8 +1030,11 @@
 /* It is possible that GLIBC has epoll but the underlying kernel doesn't.
  * Create a dummy epoll_fd to make sure epoll support is available */
 const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
-  /* TODO(ctiller): temporary, until this stabilizes */
-  if (!explicit_request) return NULL;
+  /* TODO(sreek): Temporarily disable this poller unless explicitly requested
+   * via GRPC_POLL_STRATEGY */
+  if (!explicit_request) {
+    return NULL;
+  }
 
   if (!grpc_has_wakeup_fd()) {
     return NULL;
@@ -862,6 +1054,8 @@
     return NULL;
   }
 
+  gpr_log(GPR_ERROR, "grpc epoll fd: %d", g_epfd);
+
   return &vtable;
 }
 
diff --git a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
index 9f82c48..f2f3e15 100644
--- a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
+++ b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
@@ -931,25 +931,13 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
-  bool is_fd_closed = false;
+                      bool already_closed, const char *reason) {
   grpc_error *error = GRPC_ERROR_NONE;
   polling_island *unref_pi = NULL;
 
   gpr_mu_lock(&fd->po.mu);
   fd->on_done_closure = on_done;
 
-  /* If release_fd is not NULL, we should be relinquishing control of the file
-     descriptor fd->fd (but we still own the grpc_fd structure). */
-  if (release_fd != NULL) {
-    *release_fd = fd->fd;
-  } else {
-    close(fd->fd);
-    is_fd_closed = true;
-  }
-
-  fd->orphaned = true;
-
   /* Remove the active status but keep referenced. We want this grpc_fd struct
      to be alive (and not added to freelist) until the end of this function */
   REF_BY(fd, 1, reason);
@@ -964,13 +952,23 @@
        before doing this.) */
   if (fd->po.pi != NULL) {
     polling_island *pi_latest = polling_island_lock(fd->po.pi);
-    polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error);
+    polling_island_remove_fd_locked(pi_latest, fd, already_closed, &error);
     gpr_mu_unlock(&pi_latest->mu);
 
     unref_pi = fd->po.pi;
     fd->po.pi = NULL;
   }
 
+  /* If release_fd is not NULL, we should be relinquishing control of the file
+     descriptor fd->fd (but we still own the grpc_fd structure). */
+  if (release_fd != NULL) {
+    *release_fd = fd->fd;
+  } else {
+    close(fd->fd);
+  }
+
+  fd->orphaned = true;
+
   GRPC_CLOSURE_SCHED(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error));
 
   gpr_mu_unlock(&fd->po.mu);
@@ -1008,12 +1006,12 @@
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read");
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write");
 }
 
 /*******************************************************************************
@@ -1224,7 +1222,7 @@
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_pollset *notifier) {
-  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read");
 
   /* Note, it is possible that fd_become_readable might be called twice with
      different 'notifier's when an fd becomes readable and it is in two epoll
@@ -1236,7 +1234,7 @@
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
 static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
index 49be72c..07c8ead 100644
--- a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
+++ b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
@@ -493,8 +493,8 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
-  bool is_fd_closed = false;
+                      bool already_closed, const char *reason) {
+  bool is_fd_closed = already_closed;
   grpc_error *error = GRPC_ERROR_NONE;
   epoll_set *unref_eps = NULL;
 
@@ -505,7 +505,7 @@
      descriptor fd->fd (but we still own the grpc_fd structure). */
   if (release_fd != NULL) {
     *release_fd = fd->fd;
-  } else {
+  } else if (!is_fd_closed) {
     close(fd->fd);
     is_fd_closed = true;
   }
@@ -560,12 +560,12 @@
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read");
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write");
 }
 
 /*******************************************************************************
@@ -696,11 +696,11 @@
 }
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read");
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
 static void pollset_release_epoll_set(grpc_exec_ctx *exec_ctx, grpc_pollset *ps,
diff --git a/src/core/lib/iomgr/ev_epollex_linux.c b/src/core/lib/iomgr/ev_epollex_linux.c
index 5690431..770d1fd 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.c
+++ b/src/core/lib/iomgr/ev_epollex_linux.c
@@ -380,8 +380,8 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
-  bool is_fd_closed = false;
+                      bool already_closed, const char *reason) {
+  bool is_fd_closed = already_closed;
   grpc_error *error = GRPC_ERROR_NONE;
 
   gpr_mu_lock(&fd->pollable.po.mu);
@@ -392,7 +392,7 @@
      descriptor fd->fd (but we still own the grpc_fd structure). */
   if (release_fd != NULL) {
     *release_fd = fd->fd;
-  } else {
+  } else if (!is_fd_closed) {
     close(fd->fd);
     is_fd_closed = true;
   }
@@ -438,12 +438,12 @@
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read");
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write");
 }
 
 /*******************************************************************************
@@ -710,7 +710,7 @@
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_pollset *notifier) {
-  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read");
 
   /* Note, it is possible that fd_become_readable might be called twice with
      different 'notifier's when an fd becomes readable and it is in two epoll
@@ -722,7 +722,7 @@
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
 static grpc_error *fd_become_pollable_locked(grpc_fd *fd) {
@@ -1049,8 +1049,8 @@
     /* Introduce a spurious completion.
        If we do not, then it may be that the fd-specific epoll set consumed
        a completion without being polled, leading to a missed edge going up. */
-    grpc_lfev_set_ready(exec_ctx, &had_fd->read_closure);
-    grpc_lfev_set_ready(exec_ctx, &had_fd->write_closure);
+    grpc_lfev_set_ready(exec_ctx, &had_fd->read_closure, "read");
+    grpc_lfev_set_ready(exec_ctx, &had_fd->write_closure, "write");
     pollset_kick_all(exec_ctx, pollset);
     pollset->current_pollable = &pollset->pollable;
     if (append_error(&error, pollable_materialize(&pollset->pollable),
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.c b/src/core/lib/iomgr/ev_epollsig_linux.c
index 3c4ca9c..070d75e 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.c
+++ b/src/core/lib/iomgr/ev_epollsig_linux.c
@@ -854,25 +854,13 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
-  bool is_fd_closed = false;
+                      bool already_closed, const char *reason) {
   grpc_error *error = GRPC_ERROR_NONE;
   polling_island *unref_pi = NULL;
 
   gpr_mu_lock(&fd->po.mu);
   fd->on_done_closure = on_done;
 
-  /* If release_fd is not NULL, we should be relinquishing control of the file
-     descriptor fd->fd (but we still own the grpc_fd structure). */
-  if (release_fd != NULL) {
-    *release_fd = fd->fd;
-  } else {
-    close(fd->fd);
-    is_fd_closed = true;
-  }
-
-  fd->orphaned = true;
-
   /* Remove the active status but keep referenced. We want this grpc_fd struct
      to be alive (and not added to freelist) until the end of this function */
   REF_BY(fd, 1, reason);
@@ -887,13 +875,23 @@
        before doing this.) */
   if (fd->po.pi != NULL) {
     polling_island *pi_latest = polling_island_lock(fd->po.pi);
-    polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error);
+    polling_island_remove_fd_locked(pi_latest, fd, already_closed, &error);
     gpr_mu_unlock(&pi_latest->mu);
 
     unref_pi = fd->po.pi;
     fd->po.pi = NULL;
   }
 
+  /* If release_fd is not NULL, we should be relinquishing control of the file
+     descriptor fd->fd (but we still own the grpc_fd structure). */
+  if (release_fd != NULL) {
+    *release_fd = fd->fd;
+  } else {
+    close(fd->fd);
+  }
+
+  fd->orphaned = true;
+
   GRPC_CLOSURE_SCHED(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error));
 
   gpr_mu_unlock(&fd->po.mu);
@@ -934,12 +932,12 @@
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read");
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
+  grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write");
 }
 
 /*******************************************************************************
@@ -1116,7 +1114,7 @@
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_pollset *notifier) {
-  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read");
 
   /* Note, it is possible that fd_become_readable might be called twice with
      different 'notifier's when an fd becomes readable and it is in two epoll
@@ -1128,7 +1126,7 @@
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
+  grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
 static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index 1f8d7ee..365aa58 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -398,11 +398,14 @@
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
+                      bool already_closed, const char *reason) {
   fd->on_done_closure = on_done;
   fd->released = release_fd != NULL;
-  if (fd->released) {
+  if (release_fd != NULL) {
     *release_fd = fd->fd;
+    fd->released = true;
+  } else if (already_closed) {
+    fd->released = true;
   }
   gpr_mu_lock(&fd->mu);
   REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index 2648df3..91f8cd5 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -39,10 +39,11 @@
 #include "src/core/lib/support/env.h"
 
 grpc_tracer_flag grpc_polling_trace =
-    GRPC_TRACER_INITIALIZER(false); /* Disabled by default */
+    GRPC_TRACER_INITIALIZER(false, "polling"); /* Disabled by default */
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_fd_refcount =
+    GRPC_TRACER_INITIALIZER(false, "fd_refcount");
 #endif
 
 /** Default poll() function - a pointer so that it can be overridden by some
@@ -120,11 +121,15 @@
   g_event_engine = ev_engine;
 }
 
+const grpc_event_engine_vtable *grpc_get_event_engine_test_only() {
+  return g_event_engine;
+}
+
 /* Call this only after calling grpc_event_engine_init() */
 const char *grpc_get_poll_strategy_name() { return g_poll_strategy_name; }
 
 void grpc_event_engine_init(void) {
-  grpc_register_tracer("polling", &grpc_polling_trace);
+  grpc_register_tracer(&grpc_polling_trace);
 
   char *s = gpr_getenv("GRPC_POLL_STRATEGY");
   if (s == NULL) {
@@ -165,8 +170,9 @@
 }
 
 void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    int *release_fd, const char *reason) {
-  g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason);
+                    int *release_fd, bool already_closed, const char *reason) {
+  g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, already_closed,
+                            reason);
 }
 
 void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 54c4f2e..1108e46 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -37,7 +37,7 @@
   grpc_fd *(*fd_create)(int fd, const char *name);
   int (*fd_wrapped_fd)(grpc_fd *fd);
   void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    int *release_fd, const char *reason);
+                    int *release_fd, bool already_closed, const char *reason);
   void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why);
   void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                             grpc_closure *closure);
@@ -104,7 +104,7 @@
    notify_on_write.
    MUST NOT be called with a pollset lock taken */
 void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    int *release_fd, const char *reason);
+                    int *release_fd, bool already_closed, const char *reason);
 
 /* Has grpc_fd_shutdown been called on an fd? */
 bool grpc_fd_is_shutdown(grpc_fd *fd);
@@ -153,7 +153,9 @@
 typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
 extern grpc_poll_function_type grpc_poll_function;
 
-/* This should be used for testing purposes ONLY */
+/* WARNING: The following two functions should be used for testing purposes
+ * ONLY */
 void grpc_set_event_engine_test_only(const grpc_event_engine_vtable *);
+const grpc_event_engine_vtable *grpc_get_event_engine_test_only();
 
 #endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
diff --git a/src/core/lib/iomgr/ev_windows.c b/src/core/lib/iomgr/ev_windows.c
index 027609c..c24dfae 100644
--- a/src/core/lib/iomgr/ev_windows.c
+++ b/src/core/lib/iomgr/ev_windows.c
@@ -23,6 +23,6 @@
 #include "src/core/lib/debug/trace.h"
 
 grpc_tracer_flag grpc_polling_trace =
-    GRPC_TRACER_INITIALIZER(false); /* Disabled by default */
+    GRPC_TRACER_INITIALIZER(false, "polling"); /* Disabled by default */
 
 #endif  // GRPC_WINSOCK_SOCKET
diff --git a/src/core/lib/iomgr/iomgr_posix.c b/src/core/lib/iomgr/iomgr_posix.c
index 43f5d04..f5875a2 100644
--- a/src/core/lib/iomgr/iomgr_posix.c
+++ b/src/core/lib/iomgr/iomgr_posix.c
@@ -28,7 +28,7 @@
 void grpc_iomgr_platform_init(void) {
   grpc_wakeup_fd_global_init();
   grpc_event_engine_init();
-  grpc_register_tracer("tcp", &grpc_tcp_trace);
+  grpc_register_tracer(&grpc_tcp_trace);
 }
 
 void grpc_iomgr_platform_flush(void) {}
diff --git a/src/core/lib/iomgr/iomgr_uv.c b/src/core/lib/iomgr/iomgr_uv.c
index 49d1a03..df5d23a 100644
--- a/src/core/lib/iomgr/iomgr_uv.c
+++ b/src/core/lib/iomgr/iomgr_uv.c
@@ -21,12 +21,20 @@
 #ifdef GRPC_UV
 
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/pollset_uv.h"
 #include "src/core/lib/iomgr/tcp_uv.h"
 
+gpr_thd_id g_init_thread;
+
 void grpc_iomgr_platform_init(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_pollset_global_init();
-  grpc_register_tracer("tcp", &grpc_tcp_trace);
+  grpc_register_tracer(&grpc_tcp_trace);
+  grpc_executor_set_threading(&exec_ctx, false);
+  g_init_thread = gpr_thd_currentid();
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 void grpc_iomgr_platform_flush(void) {}
 void grpc_iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); }
diff --git a/src/core/lib/iomgr/iomgr_uv.h b/src/core/lib/iomgr/iomgr_uv.h
new file mode 100644
index 0000000..3b4daaa
--- /dev/null
+++ b/src/core/lib/iomgr/iomgr_uv.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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_LIB_IOMGR_IOMGR_UV_H
+#define GRPC_CORE_LIB_IOMGR_IOMGR_UV_H
+
+#include "src/core/lib/iomgr/iomgr_internal.h"
+
+#include <grpc/support/thd.h>
+
+/* The thread ID of the thread on which grpc was initialized. Used to verify
+ * that all calls into libuv are made on that same thread */
+extern gpr_thd_id g_init_thread;
+
+#ifdef GRPC_UV_THREAD_CHECK
+#define GRPC_UV_ASSERT_SAME_THREAD() \
+  GPR_ASSERT(gpr_thd_currentid() == g_init_thread)
+#else
+#define GRPC_UV_ASSERT_SAME_THREAD()
+#endif /* GRPC_UV_THREAD_CHECK */
+
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_UV_H */
diff --git a/src/core/lib/iomgr/lockfree_event.c b/src/core/lib/iomgr/lockfree_event.c
index c2ceecb..f967b22 100644
--- a/src/core/lib/iomgr/lockfree_event.c
+++ b/src/core/lib/iomgr/lockfree_event.c
@@ -79,12 +79,12 @@
 }
 
 void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state,
-                         grpc_closure *closure) {
+                         grpc_closure *closure, const char *variable) {
   while (true) {
     gpr_atm curr = gpr_atm_no_barrier_load(state);
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG, "lfev_notify_on: %p curr=%p closure=%p", state,
-              (void *)curr, closure);
+      gpr_log(GPR_ERROR, "lfev_notify_on[%s]: %p curr=%p closure=%p", variable,
+              state, (void *)curr, closure);
     }
     switch (curr) {
       case CLOSURE_NOT_READY: {
@@ -149,7 +149,7 @@
   while (true) {
     gpr_atm curr = gpr_atm_no_barrier_load(state);
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG, "lfev_set_shutdown: %p curr=%p err=%s", state,
+      gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", state,
               (void *)curr, grpc_error_string(shutdown_err));
     }
     switch (curr) {
@@ -193,12 +193,14 @@
   GPR_UNREACHABLE_CODE(return false);
 }
 
-void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state) {
+void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state,
+                         const char *variable) {
   while (true) {
     gpr_atm curr = gpr_atm_no_barrier_load(state);
 
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG, "lfev_set_ready: %p curr=%p", state, (void *)curr);
+      gpr_log(GPR_ERROR, "lfev_set_ready[%s]: %p curr=%p", variable, state,
+              (void *)curr);
     }
 
     switch (curr) {
diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h
index ef3844a..6a14a0f 100644
--- a/src/core/lib/iomgr/lockfree_event.h
+++ b/src/core/lib/iomgr/lockfree_event.h
@@ -30,10 +30,11 @@
 bool grpc_lfev_is_shutdown(gpr_atm *state);
 
 void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state,
-                         grpc_closure *closure);
+                         grpc_closure *closure, const char *variable);
 /* Returns true on first successful shutdown */
 bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state,
                             grpc_error *shutdown_err);
-void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state);
+void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state,
+                         const char *variable);
 
 #endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */
diff --git a/src/core/lib/iomgr/nameser.h b/src/core/lib/iomgr/nameser.h
new file mode 100644
index 0000000..daed6de
--- /dev/null
+++ b/src/core/lib/iomgr/nameser.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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_LIB_IOMGR_NAMESER_H
+#define GRPC_CORE_LIB_IOMGR_NAMESER_H
+
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_HAVE_ARPA_NAMESER
+
+#include <arpa/nameser.h>
+
+#else /* GRPC_HAVE_ARPA_NAMESER */
+
+typedef enum __ns_class {
+  ns_c_invalid = 0, /* Cookie. */
+  ns_c_in = 1,      /* Internet. */
+  ns_c_2 = 2,       /* unallocated/unsupported. */
+  ns_c_chaos = 3,   /* MIT Chaos-net. */
+  ns_c_hs = 4,      /* MIT Hesiod. */
+  /* Query class values which do not appear in resource records */
+  ns_c_none = 254, /* for prereq. sections in update requests */
+  ns_c_any = 255,  /* Wildcard match. */
+  ns_c_max = 65536
+} ns_class;
+
+typedef enum __ns_type {
+  ns_t_invalid = 0,   /* Cookie. */
+  ns_t_a = 1,         /* Host address. */
+  ns_t_ns = 2,        /* Authoritative server. */
+  ns_t_md = 3,        /* Mail destination. */
+  ns_t_mf = 4,        /* Mail forwarder. */
+  ns_t_cname = 5,     /* Canonical name. */
+  ns_t_soa = 6,       /* Start of authority zone. */
+  ns_t_mb = 7,        /* Mailbox domain name. */
+  ns_t_mg = 8,        /* Mail group member. */
+  ns_t_mr = 9,        /* Mail rename name. */
+  ns_t_null = 10,     /* Null resource record. */
+  ns_t_wks = 11,      /* Well known service. */
+  ns_t_ptr = 12,      /* Domain name pointer. */
+  ns_t_hinfo = 13,    /* Host information. */
+  ns_t_minfo = 14,    /* Mailbox information. */
+  ns_t_mx = 15,       /* Mail routing information. */
+  ns_t_txt = 16,      /* Text strings. */
+  ns_t_rp = 17,       /* Responsible person. */
+  ns_t_afsdb = 18,    /* AFS cell database. */
+  ns_t_x25 = 19,      /* X_25 calling address. */
+  ns_t_isdn = 20,     /* ISDN calling address. */
+  ns_t_rt = 21,       /* Router. */
+  ns_t_nsap = 22,     /* NSAP address. */
+  ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
+  ns_t_sig = 24,      /* Security signature. */
+  ns_t_key = 25,      /* Security key. */
+  ns_t_px = 26,       /* X.400 mail mapping. */
+  ns_t_gpos = 27,     /* Geographical position (withdrawn). */
+  ns_t_aaaa = 28,     /* Ip6 Address. */
+  ns_t_loc = 29,      /* Location Information. */
+  ns_t_nxt = 30,      /* Next domain (security). */
+  ns_t_eid = 31,      /* Endpoint identifier. */
+  ns_t_nimloc = 32,   /* Nimrod Locator. */
+  ns_t_srv = 33,      /* Server Selection. */
+  ns_t_atma = 34,     /* ATM Address */
+  ns_t_naptr = 35,    /* Naming Authority PoinTeR */
+  ns_t_kx = 36,       /* Key Exchange */
+  ns_t_cert = 37,     /* Certification record */
+  ns_t_a6 = 38,       /* IPv6 address (deprecates AAAA) */
+  ns_t_dname = 39,    /* Non-terminal DNAME (for IPv6) */
+  ns_t_sink = 40,     /* Kitchen sink (experimentatl) */
+  ns_t_opt = 41,      /* EDNS0 option (meta-RR) */
+  ns_t_apl = 42,      /* Address prefix list (RFC3123) */
+  ns_t_ds = 43,       /* Delegation Signer (RFC4034) */
+  ns_t_sshfp = 44,    /* SSH Key Fingerprint (RFC4255) */
+  ns_t_rrsig = 46,    /* Resource Record Signature (RFC4034) */
+  ns_t_nsec = 47,     /* Next Secure (RFC4034) */
+  ns_t_dnskey = 48,   /* DNS Public Key (RFC4034) */
+  ns_t_tkey = 249,    /* Transaction key */
+  ns_t_tsig = 250,    /* Transaction signature. */
+  ns_t_ixfr = 251,    /* Incremental zone transfer. */
+  ns_t_axfr = 252,    /* Transfer zone of authority. */
+  ns_t_mailb = 253,   /* Transfer mailbox records. */
+  ns_t_maila = 254,   /* Transfer mail agent records. */
+  ns_t_any = 255,     /* Wildcard match. */
+  ns_t_zxfr = 256,    /* BIND-specific, nonstandard. */
+  ns_t_max = 65536
+} ns_type;
+
+#endif /* GRPC_HAVE_ARPA_NAMESER */
+
+#endif /* GRPC_CORE_LIB_IOMGR_NAMESER_H */
diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c
index 1a54065..a79fe89 100644
--- a/src/core/lib/iomgr/pollset_uv.c
+++ b/src/core/lib/iomgr/pollset_uv.c
@@ -28,13 +28,15 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/pollset.h"
 #include "src/core/lib/iomgr/pollset_uv.h"
 
 #include "src/core/lib/debug/trace.h"
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_fd_refcount =
+    GRPC_TRACER_INITIALIZER(false, "fd_refcount");
 #endif
 
 struct grpc_pollset {
@@ -69,6 +71,7 @@
 }
 
 void grpc_pollset_global_shutdown(void) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   gpr_mu_destroy(&grpc_polling_mu);
   uv_close((uv_handle_t *)dummy_uv_handle, dummy_handle_close_cb);
 }
@@ -78,6 +81,7 @@
 static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; }
 
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   *mu = &grpc_polling_mu;
   uv_timer_init(uv_default_loop(), &pollset->timer);
   pollset->shutting_down = 0;
@@ -86,6 +90,7 @@
 void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_closure *closure) {
   GPR_ASSERT(!pollset->shutting_down);
+  GRPC_UV_ASSERT_SAME_THREAD();
   pollset->shutting_down = 1;
   if (grpc_pollset_work_run_loop) {
     // Drain any pending UV callbacks without blocking
@@ -98,6 +103,7 @@
 }
 
 void grpc_pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   uv_close((uv_handle_t *)&pollset->timer, timer_close_cb);
   // timer.data is a boolean indicating that the timer has finished closing
   pollset->timer.data = (void *)0;
@@ -112,6 +118,7 @@
                               grpc_pollset_worker **worker_hdl,
                               gpr_timespec now, gpr_timespec deadline) {
   uint64_t timeout;
+  GRPC_UV_ASSERT_SAME_THREAD();
   gpr_mu_unlock(&grpc_polling_mu);
   if (grpc_pollset_work_run_loop) {
     if (gpr_time_cmp(deadline, now) >= 0) {
@@ -140,6 +147,7 @@
 
 grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
                               grpc_pollset_worker *specific_worker) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0);
   return GRPC_ERROR_NONE;
 }
diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c
index 1bfc2a2..ea017a6 100644
--- a/src/core/lib/iomgr/pollset_windows.c
+++ b/src/core/lib/iomgr/pollset_windows.c
@@ -31,7 +31,8 @@
 #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_fd_refcount =
+    GRPC_TRACER_INITIALIZER(false, "fd_refcount");
 #endif
 
 gpr_mu grpc_polling_mu;
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index f5d15b4..c12058f 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -24,6 +24,7 @@
 #if defined(GRPC_UV)
 // Do nothing
 #elif defined(GPR_MANYLINUX1)
+#define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_HAVE_IFADDRS 1
 #define GRPC_HAVE_IPV6_RECVPKTINFO 1
 #define GRPC_HAVE_IP_PKTINFO 1
@@ -51,6 +52,7 @@
 #define GRPC_POSIX_WAKEUP_FD 1
 #define GRPC_TIMER_USE_GENERIC 1
 #elif defined(GPR_LINUX)
+#define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_HAVE_IFADDRS 1
 #define GRPC_HAVE_IPV6_RECVPKTINFO 1
 #define GRPC_HAVE_IP_PKTINFO 1
@@ -82,6 +84,7 @@
 #define GRPC_POSIX_SOCKETUTILS
 #endif
 #elif defined(GPR_APPLE)
+#define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_HAVE_IFADDRS 1
 #define GRPC_HAVE_SO_NOSIGPIPE 1
 #define GRPC_HAVE_UNIX_SOCKET 1
@@ -93,6 +96,7 @@
 #define GRPC_POSIX_WAKEUP_FD 1
 #define GRPC_TIMER_USE_GENERIC 1
 #elif defined(GPR_FREEBSD)
+#define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_HAVE_IFADDRS 1
 #define GRPC_HAVE_IPV6_RECVPKTINFO 1
 #define GRPC_HAVE_SO_NOSIGPIPE 1
@@ -104,6 +108,7 @@
 #define GRPC_POSIX_WAKEUP_FD 1
 #define GRPC_TIMER_USE_GENERIC 1
 #elif defined(GPR_NACL)
+#define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
 #define GRPC_POSIX_SOCKET 1
 #define GRPC_POSIX_SOCKETADDR 1
diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c
index a98b8e6..2d438e8 100644
--- a/src/core/lib/iomgr/resolve_address_uv.c
+++ b/src/core/lib/iomgr/resolve_address_uv.c
@@ -30,6 +30,7 @@
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
@@ -114,11 +115,14 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_error *error;
   int retry_status;
+  char *port = r->port;
 
   gpr_free(req);
   retry_status = retry_named_port_failure(status, r, getaddrinfo_callback);
   if (retry_status == 0) {
-    // The request is being retried. Nothing should be done here
+    /* The request is being retried. It is using its own port string, so we free
+     * the original one */
+    gpr_free(port);
     return;
   }
   /* Either no retry was attempted, or the retry failed. Either way, the
@@ -171,6 +175,8 @@
   grpc_error *err;
   int retry_status;
 
+  GRPC_UV_ASSERT_SAME_THREAD();
+
   req.addrinfo = NULL;
 
   err = try_split_host_port(name, default_port, &host, &port);
@@ -218,16 +224,19 @@
                                  grpc_pollset_set *interested_parties,
                                  grpc_closure *on_done,
                                  grpc_resolved_addresses **addrs) {
-  uv_getaddrinfo_t *req;
-  request *r;
-  struct addrinfo *hints;
-  char *host;
-  char *port;
+  uv_getaddrinfo_t *req = NULL;
+  request *r = NULL;
+  struct addrinfo *hints = NULL;
+  char *host = NULL;
+  char *port = NULL;
   grpc_error *err;
   int s;
+  GRPC_UV_ASSERT_SAME_THREAD();
   err = try_split_host_port(name, default_port, &host, &port);
   if (err != GRPC_ERROR_NONE) {
     GRPC_CLOSURE_SCHED(exec_ctx, on_done, err);
+    gpr_free(host);
+    gpr_free(port);
     return;
   }
   r = gpr_malloc(sizeof(request));
diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c
index f2cc1be..a31d9ee 100644
--- a/src/core/lib/iomgr/resource_quota.c
+++ b/src/core/lib/iomgr/resource_quota.c
@@ -29,7 +29,8 @@
 
 #include "src/core/lib/iomgr/combiner.h"
 
-grpc_tracer_flag grpc_resource_quota_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_resource_quota_trace =
+    GRPC_TRACER_INITIALIZER(false, "resource_quota");
 
 #define MEMORY_USAGE_ESTIMATION_MAX 65536
 
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
index 99dc2f1..3f4145d 100644
--- a/src/core/lib/iomgr/sockaddr_utils.c
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -220,6 +220,11 @@
   return NULL;
 }
 
+int grpc_sockaddr_get_family(const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
+  return addr->sa_family;
+}
+
 int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {
   const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   switch (addr->sa_family) {
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
index 7692b96..a589a19 100644
--- a/src/core/lib/iomgr/sockaddr_utils.h
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -75,4 +75,6 @@
 /* Returns the URI scheme corresponding to \a addr */
 const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr);
 
+int grpc_sockaddr_get_family(const grpc_resolved_address *resolved_addr);
+
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
index 21e320a..a25fba4 100644
--- a/src/core/lib/iomgr/tcp_client_posix.c
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -209,7 +209,8 @@
 finish:
   if (fd != NULL) {
     grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
-    grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
+    grpc_fd_orphan(exec_ctx, fd, NULL, NULL, false /* already_closed */,
+                   "tcp_client_orphan");
     fd = NULL;
   }
   done = (--ac->refs == 0);
@@ -295,7 +296,8 @@
   }
 
   if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
-    grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
+    grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, false /* already_closed */,
+                   "tcp_client_connect_error");
     GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect"));
     goto done;
   }
diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c
index 2f1d237..786c456 100644
--- a/src/core/lib/iomgr/tcp_client_uv.c
+++ b/src/core/lib/iomgr/tcp_client_uv.c
@@ -26,6 +26,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/iomgr/tcp_uv.h"
@@ -124,6 +125,8 @@
   (void)channel_args;
   (void)interested_parties;
 
+  GRPC_UV_ASSERT_SAME_THREAD();
+
   if (channel_args != NULL) {
     for (size_t i = 0; i < channel_args->num_args; i++) {
       if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
index 5de2b0f..2f543fd 100644
--- a/src/core/lib/iomgr/tcp_posix.c
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -59,7 +59,7 @@
 typedef size_t msg_iovlen_type;
 #endif
 
-grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false, "tcp");
 
 typedef struct {
   grpc_endpoint base;
@@ -156,7 +156,7 @@
 
 static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
   grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
-                 "tcp_unref_orphan");
+                 false /* already_closed */, "tcp_unref_orphan");
   grpc_slice_buffer_destroy_internal(exec_ctx, &tcp->last_read_buffer);
   grpc_resource_user_unref(exec_ctx, tcp->resource_user);
   gpr_free(tcp->peer_string);
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index f304642..0fc5c0f 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -166,7 +166,7 @@
       GRPC_CLOSURE_INIT(&sp->destroyed_closure, destroyed_port, s,
                         grpc_schedule_on_exec_ctx);
       grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
-                     "tcp_listener_shutdown");
+                     false /* already_closed */, "tcp_listener_shutdown");
     }
     gpr_mu_unlock(&s->mu);
   } else {
diff --git a/src/core/lib/iomgr/tcp_server_uv.c b/src/core/lib/iomgr/tcp_server_uv.c
index 2ab836c..3b93323 100644
--- a/src/core/lib/iomgr/tcp_server_uv.c
+++ b/src/core/lib/iomgr/tcp_server_uv.c
@@ -20,6 +20,7 @@
 
 #ifdef GRPC_UV
 
+#include <assert.h>
 #include <string.h>
 
 #include <grpc/support/alloc.h>
@@ -27,6 +28,7 @@
 
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/tcp_server.h"
@@ -43,6 +45,8 @@
   struct grpc_tcp_listener *next;
 
   bool closed;
+
+  bool has_pending_connection;
 };
 
 struct grpc_tcp_server {
@@ -104,6 +108,7 @@
 }
 
 grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   gpr_ref(&s->refs);
   return s;
 }
@@ -168,6 +173,7 @@
 }
 
 void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   if (gpr_unref(&s->refs)) {
     /* Complete shutdown_starting work before destroying. */
     grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -183,18 +189,49 @@
   }
 }
 
-static void accepted_connection_close_cb(uv_handle_t *handle) {
-  gpr_free(handle);
+static void finish_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *sp) {
+  grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor));
+  uv_tcp_t *client;
+  grpc_endpoint *ep = NULL;
+  grpc_resolved_address peer_name;
+  char *peer_name_string;
+  int err;
+  uv_tcp_t *server = sp->handle;
+
+  client = gpr_malloc(sizeof(uv_tcp_t));
+  uv_tcp_init(uv_default_loop(), client);
+  // UV documentation says this is guaranteed to succeed
+  uv_accept((uv_stream_t *)server, (uv_stream_t *)client);
+  peer_name_string = NULL;
+  memset(&peer_name, 0, sizeof(grpc_resolved_address));
+  peer_name.len = sizeof(struct sockaddr_storage);
+  err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name.addr,
+                           (int *)&peer_name.len);
+  if (err == 0) {
+    peer_name_string = grpc_sockaddr_to_uri(&peer_name);
+  } else {
+    gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", uv_strerror(err));
+  }
+  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
+    if (peer_name_string) {
+      gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection: %s",
+              sp->server, peer_name_string);
+    } else {
+      gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection", sp->server);
+    }
+  }
+  ep = grpc_tcp_create(client, sp->server->resource_quota, peer_name_string);
+  acceptor->from_server = sp->server;
+  acceptor->port_index = sp->port_index;
+  acceptor->fd_index = 0;
+  sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, NULL,
+                           acceptor);
+  gpr_free(peer_name_string);
 }
 
 static void on_connect(uv_stream_t *server, int status) {
   grpc_tcp_listener *sp = (grpc_tcp_listener *)server->data;
-  uv_tcp_t *client;
-  grpc_endpoint *ep = NULL;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_resolved_address peer_name;
-  char *peer_name_string;
-  int err;
 
   if (status < 0) {
     switch (status) {
@@ -207,35 +244,19 @@
     }
   }
 
-  client = gpr_malloc(sizeof(uv_tcp_t));
-  uv_tcp_init(uv_default_loop(), client);
-  // UV documentation says this is guaranteed to succeed
-  uv_accept((uv_stream_t *)server, (uv_stream_t *)client);
-  // If the server has not been started, we discard incoming connections
-  if (sp->server->on_accept_cb == NULL) {
-    uv_close((uv_handle_t *)client, accepted_connection_close_cb);
-  } else {
-    peer_name_string = NULL;
-    memset(&peer_name, 0, sizeof(grpc_resolved_address));
-    peer_name.len = sizeof(struct sockaddr_storage);
-    err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name.addr,
-                             (int *)&peer_name.len);
-    if (err == 0) {
-      peer_name_string = grpc_sockaddr_to_uri(&peer_name);
-    } else {
-      gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", uv_strerror(status));
-    }
-    ep = grpc_tcp_create(client, sp->server->resource_quota, peer_name_string);
-    // Create acceptor.
-    grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor));
-    acceptor->from_server = sp->server;
-    acceptor->port_index = sp->port_index;
-    acceptor->fd_index = 0;
-    sp->server->on_accept_cb(&exec_ctx, sp->server->on_accept_cb_arg, ep, NULL,
-                             acceptor);
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_free(peer_name_string);
+  GPR_ASSERT(!sp->has_pending_connection);
+
+  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
+    gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p incoming connection", sp->server);
   }
+
+  // Create acceptor.
+  if (sp->server->on_accept_cb) {
+    finish_accept(&exec_ctx, sp);
+  } else {
+    sp->has_pending_connection = true;
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle,
@@ -282,7 +303,7 @@
 
   GPR_ASSERT(port >= 0);
   GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-  sp = gpr_malloc(sizeof(grpc_tcp_listener));
+  sp = gpr_zalloc(sizeof(grpc_tcp_listener));
   sp->next = NULL;
   if (s->head == NULL) {
     s->head = sp;
@@ -316,6 +337,9 @@
   unsigned port_index = 0;
   int status;
   grpc_error *error = GRPC_ERROR_NONE;
+  int family;
+
+  GRPC_UV_ASSERT_SAME_THREAD();
 
   if (s->tail != NULL) {
     port_index = s->tail->port_index + 1;
@@ -353,7 +377,18 @@
   }
 
   handle = gpr_malloc(sizeof(uv_tcp_t));
-  status = uv_tcp_init(uv_default_loop(), handle);
+
+  family = grpc_sockaddr_get_family(addr);
+  status = uv_tcp_init_ex(uv_default_loop(), handle, (unsigned int)family);
+#if defined(GPR_LINUX) && defined(SO_REUSEPORT)
+  if (family == AF_INET || family == AF_INET6) {
+    int fd;
+    uv_fileno((uv_handle_t *)handle, &fd);
+    int enable = 1;
+    setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
+  }
+#endif /* GPR_LINUX && SO_REUSEPORT */
+
   if (status == 0) {
     error = add_socket_to_server(s, handle, addr, port_index, &sp);
   } else {
@@ -366,6 +401,18 @@
 
   gpr_free(allocated_addr);
 
+  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
+    char *port_string;
+    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_free(port_string);
+    } else {
+      gpr_log(GPR_DEBUG, "SERVER %p add_port error=%s", s, str);
+    }
+  }
+
   if (error != GRPC_ERROR_NONE) {
     grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
         "Failed to add port to server", &error, 1);
@@ -385,13 +432,19 @@
   grpc_tcp_listener *sp;
   (void)pollsets;
   (void)pollset_count;
+  GRPC_UV_ASSERT_SAME_THREAD();
+  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
+    gpr_log(GPR_DEBUG, "SERVER_START %p", server);
+  }
   GPR_ASSERT(on_accept_cb);
   GPR_ASSERT(!server->on_accept_cb);
   server->on_accept_cb = on_accept_cb;
   server->on_accept_cb_arg = cb_arg;
   for (sp = server->head; sp; sp = sp->next) {
-    GPR_ASSERT(uv_listen((uv_stream_t *)sp->handle, SOMAXCONN, on_connect) ==
-               0);
+    if (sp->has_pending_connection) {
+      finish_accept(exec_ctx, sp);
+      sp->has_pending_connection = false;
+    }
   }
 }
 
diff --git a/src/core/lib/iomgr/tcp_uv.c b/src/core/lib/iomgr/tcp_uv.c
index ff5fd3e..a05c19b 100644
--- a/src/core/lib/iomgr/tcp_uv.c
+++ b/src/core/lib/iomgr/tcp_uv.c
@@ -30,6 +30,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/network_status_tracker.h"
 #include "src/core/lib/iomgr/resource_quota.h"
 #include "src/core/lib/iomgr/tcp_uv.h"
@@ -37,7 +38,7 @@
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 
-grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false, "tcp");
 
 typedef struct {
   grpc_endpoint base;
@@ -183,6 +184,7 @@
   grpc_tcp *tcp = (grpc_tcp *)ep;
   int status;
   grpc_error *error = GRPC_ERROR_NONE;
+  GRPC_UV_ASSERT_SAME_THREAD();
   GPR_ASSERT(tcp->read_cb == NULL);
   tcp->read_cb = cb;
   tcp->read_slices = read_slices;
@@ -236,6 +238,7 @@
   unsigned int i;
   grpc_slice *slice;
   uv_write_t *write_req;
+  GRPC_UV_ASSERT_SAME_THREAD();
 
   if (GRPC_TRACER_ON(grpc_tcp_trace)) {
     size_t j;
@@ -307,6 +310,10 @@
                                  grpc_error *why) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
   if (!tcp->shutting_down) {
+    if (GRPC_TRACER_ON(grpc_tcp_trace)) {
+      const char *str = grpc_error_string(why);
+      gpr_log(GPR_DEBUG, "TCP %p shutdown why=%s", tcp->handle, str);
+    }
     tcp->shutting_down = true;
     uv_shutdown_t *req = &tcp->shutdown_req;
     uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c
index 6704a15..2cbb974 100644
--- a/src/core/lib/iomgr/tcp_windows.c
+++ b/src/core/lib/iomgr/tcp_windows.c
@@ -48,7 +48,7 @@
 #define GRPC_FIONBIO FIONBIO
 #endif
 
-grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false, "tcp");
 
 static grpc_error *set_non_block(SOCKET sock) {
   int status;
diff --git a/src/core/lib/iomgr/timer_generic.c b/src/core/lib/iomgr/timer_generic.c
index e6a9eb0..12efce2 100644
--- a/src/core/lib/iomgr/timer_generic.c
+++ b/src/core/lib/iomgr/timer_generic.c
@@ -41,8 +41,9 @@
 #define MIN_QUEUE_WINDOW_DURATION 0.01
 #define MAX_QUEUE_WINDOW_DURATION 1
 
-grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false);
-grpc_tracer_flag grpc_timer_check_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false, "timer");
+grpc_tracer_flag grpc_timer_check_trace =
+    GRPC_TRACER_INITIALIZER(false, "timer_check");
 
 /* A "timer shard". Contains a 'heap' and a 'list' of timers. All timers with
  * deadlines earlier than 'queue_deadline" cap are maintained in the heap and
@@ -160,8 +161,8 @@
   g_shared_mutables.min_timer = timespec_to_atm_round_down(now);
   gpr_tls_init(&g_last_seen_min_timer);
   gpr_tls_set(&g_last_seen_min_timer, 0);
-  grpc_register_tracer("timer", &grpc_timer_trace);
-  grpc_register_tracer("timer_check", &grpc_timer_check_trace);
+  grpc_register_tracer(&grpc_timer_trace);
+  grpc_register_tracer(&grpc_timer_check_trace);
 
   for (i = 0; i < NUM_SHARDS; i++) {
     timer_shard *shard = &g_shards[i];
diff --git a/src/core/lib/iomgr/timer_manager.c b/src/core/lib/iomgr/timer_manager.c
index cb7998d..631f793 100644
--- a/src/core/lib/iomgr/timer_manager.c
+++ b/src/core/lib/iomgr/timer_manager.c
@@ -56,7 +56,7 @@
 // generation counter to track which thread is waiting for the next timer
 static uint64_t g_timed_waiter_generation;
 
-static void timer_thread(void *unused);
+static void timer_thread(void *completed_thread_ptr);
 
 static void gc_completed_threads(void) {
   if (g_completed_threads != NULL) {
@@ -81,10 +81,17 @@
   if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
     gpr_log(GPR_DEBUG, "Spawn timer thread");
   }
-  gpr_thd_id thd;
   gpr_thd_options opt = gpr_thd_options_default();
   gpr_thd_options_set_joinable(&opt);
-  gpr_thd_new(&thd, timer_thread, NULL, &opt);
+  completed_thread *ct = gpr_malloc(sizeof(*ct));
+  // The call to gpr_thd_new() has to be under the same lock used by
+  // gc_completed_threads(), particularly due to ct->t, which is written here
+  // (internally by gpr_thd_new) and read there. Otherwise it's possible for ct
+  // to leak through g_completed_threads and be freed in gc_completed_threads()
+  // before "&ct->t" is written to, causing a use-after-free.
+  gpr_mu_lock(&g_mu);
+  gpr_thd_new(&ct->t, timer_thread, ct, &opt);
+  gpr_mu_unlock(&g_mu);
 }
 
 void grpc_timer_manager_tick() {
@@ -245,7 +252,7 @@
   }
 }
 
-static void timer_thread_cleanup(void) {
+static void timer_thread_cleanup(completed_thread *ct) {
   gpr_mu_lock(&g_mu);
   // terminate the thread: drop the waiter count, thread count, and let whomever
   // stopped the threading stuff know that we're done
@@ -254,8 +261,6 @@
   if (0 == g_thread_count) {
     gpr_cv_signal(&g_cv_shutdown);
   }
-  completed_thread *ct = gpr_malloc(sizeof(*ct));
-  ct->t = gpr_thd_currentid();
   ct->next = g_completed_threads;
   g_completed_threads = ct;
   gpr_mu_unlock(&g_mu);
@@ -264,14 +269,14 @@
   }
 }
 
-static void timer_thread(void *unused) {
+static void timer_thread(void *completed_thread_ptr) {
   // this threads exec_ctx: we try to run things through to completion here
   // since it's easy to spin up new threads
   grpc_exec_ctx exec_ctx =
       GRPC_EXEC_CTX_INITIALIZER(0, grpc_never_ready_to_finish, NULL);
   timer_main_loop(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
-  timer_thread_cleanup();
+  timer_thread_cleanup(completed_thread_ptr);
 }
 
 static void start_threads(void) {
diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c
index 4f204cf..70f49bc 100644
--- a/src/core/lib/iomgr/timer_uv.c
+++ b/src/core/lib/iomgr/timer_uv.c
@@ -24,12 +24,14 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/iomgr_uv.h"
 #include "src/core/lib/iomgr/timer.h"
 
 #include <uv.h>
 
-grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false);
-grpc_tracer_flag grpc_timer_check_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false, "timer");
+grpc_tracer_flag grpc_timer_check_trace =
+    GRPC_TRACER_INITIALIZER(false, "timer_check");
 
 static void timer_close_callback(uv_handle_t *handle) { gpr_free(handle); }
 
@@ -42,6 +44,7 @@
 void run_expired_timer(uv_timer_t *handle) {
   grpc_timer *timer = (grpc_timer *)handle->data;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_UV_ASSERT_SAME_THREAD();
   GPR_ASSERT(timer->pending);
   timer->pending = 0;
   GRPC_CLOSURE_SCHED(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
@@ -54,6 +57,7 @@
                      gpr_timespec now) {
   uint64_t timeout;
   uv_timer_t *uv_timer;
+  GRPC_UV_ASSERT_SAME_THREAD();
   timer->closure = closure;
   if (gpr_time_cmp(deadline, now) <= 0) {
     timer->pending = 0;
@@ -74,6 +78,7 @@
 }
 
 void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
+  GRPC_UV_ASSERT_SAME_THREAD();
   if (timer->pending) {
     timer->pending = 0;
     GRPC_CLOSURE_SCHED(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
index 54e7f41..88fa34c 100644
--- a/src/core/lib/iomgr/udp_server.c
+++ b/src/core/lib/iomgr/udp_server.c
@@ -214,7 +214,7 @@
                       sp->server->user_data);
       }
       grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
-                     "udp_listener_shutdown");
+                     false /* already_closed */, "udp_listener_shutdown");
     }
     gpr_mu_unlock(&s->mu);
   } else {
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
index dffe6d2..8fff2c9 100644
--- a/src/core/lib/security/context/security_context.c
+++ b/src/core/lib/security/context/security_context.c
@@ -31,7 +31,7 @@
 
 #ifndef NDEBUG
 grpc_tracer_flag grpc_trace_auth_context_refcount =
-    GRPC_TRACER_INITIALIZER(false);
+    GRPC_TRACER_INITIALIZER(false, "auth_context_refcount");
 #endif
 
 /* --- grpc_call --- */
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
index 77d7b04..09fd60a 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.c
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -32,88 +32,98 @@
 typedef struct {
   grpc_composite_call_credentials *composite_creds;
   size_t creds_index;
-  grpc_credentials_md_store *md_elems;
-  grpc_auth_metadata_context auth_md_context;
-  void *user_data;
   grpc_polling_entity *pollent;
-  grpc_credentials_metadata_cb cb;
+  grpc_auth_metadata_context auth_md_context;
+  grpc_credentials_mdelem_array *md_array;
+  grpc_closure *on_request_metadata;
+  grpc_closure internal_on_request_metadata;
 } grpc_composite_call_credentials_metadata_context;
 
 static void composite_call_destruct(grpc_exec_ctx *exec_ctx,
                                     grpc_call_credentials *creds) {
   grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->inner.num_creds; i++) {
+  for (size_t i = 0; i < c->inner.num_creds; i++) {
     grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]);
   }
   gpr_free(c->inner.creds_array);
 }
 
-static void composite_call_md_context_destroy(
-    grpc_exec_ctx *exec_ctx,
-    grpc_composite_call_credentials_metadata_context *ctx) {
-  grpc_credentials_md_store_unref(exec_ctx, ctx->md_elems);
+static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *arg,
+                                       grpc_error *error) {
+  grpc_composite_call_credentials_metadata_context *ctx =
+      (grpc_composite_call_credentials_metadata_context *)arg;
+  if (error == GRPC_ERROR_NONE) {
+    /* See if we need to get some more metadata. */
+    if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+      grpc_call_credentials *inner_creds =
+          ctx->composite_creds->inner.creds_array[ctx->creds_index++];
+      if (grpc_call_credentials_get_request_metadata(
+              exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
+              ctx->md_array, &ctx->internal_on_request_metadata, &error)) {
+        // Synchronous response, so call ourselves recursively.
+        composite_call_metadata_cb(exec_ctx, arg, error);
+        GRPC_ERROR_UNREF(error);
+      }
+      return;
+    }
+    // We're done!
+  }
+  GRPC_CLOSURE_SCHED(exec_ctx, ctx->on_request_metadata, GRPC_ERROR_REF(error));
   gpr_free(ctx);
 }
 
-static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       grpc_credentials_md *md_elems,
-                                       size_t num_md,
-                                       grpc_credentials_status status,
-                                       const char *error_details) {
-  grpc_composite_call_credentials_metadata_context *ctx =
-      (grpc_composite_call_credentials_metadata_context *)user_data;
-  if (status != GRPC_CREDENTIALS_OK) {
-    ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status, error_details);
-    return;
-  }
-
-  /* Copy the metadata in the context. */
-  if (num_md > 0) {
-    size_t i;
-    for (i = 0; i < num_md; i++) {
-      grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
-                                    md_elems[i].value);
-    }
-  }
-
-  /* See if we need to get some more metadata. */
-  if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
-    grpc_call_credentials *inner_creds =
-        ctx->composite_creds->inner.creds_array[ctx->creds_index++];
-    grpc_call_credentials_get_request_metadata(
-        exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
-        composite_call_metadata_cb, ctx);
-    return;
-  }
-
-  /* We're done!. */
-  ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
-          ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK, NULL);
-  composite_call_md_context_destroy(exec_ctx, ctx);
-}
-
-static void composite_call_get_request_metadata(
+static bool composite_call_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context auth_md_context,
-    grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error) {
   grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
   grpc_composite_call_credentials_metadata_context *ctx;
-
   ctx = gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context));
-  ctx->auth_md_context = auth_md_context;
-  ctx->user_data = user_data;
-  ctx->cb = cb;
   ctx->composite_creds = c;
   ctx->pollent = pollent;
-  ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
-  grpc_call_credentials_get_request_metadata(
-      exec_ctx, c->inner.creds_array[ctx->creds_index++], ctx->pollent,
-      auth_md_context, composite_call_metadata_cb, ctx);
+  ctx->auth_md_context = auth_md_context;
+  ctx->md_array = md_array;
+  ctx->on_request_metadata = on_request_metadata;
+  GRPC_CLOSURE_INIT(&ctx->internal_on_request_metadata,
+                    composite_call_metadata_cb, ctx, grpc_schedule_on_exec_ctx);
+  while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+    grpc_call_credentials *inner_creds =
+        ctx->composite_creds->inner.creds_array[ctx->creds_index++];
+    if (grpc_call_credentials_get_request_metadata(
+            exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
+            ctx->md_array, &ctx->internal_on_request_metadata, error)) {
+      if (*error != GRPC_ERROR_NONE) break;
+    } else {
+      break;
+    }
+  }
+  // If we got through all creds synchronously or we got a synchronous
+  // error on one of them, return synchronously.
+  if (ctx->creds_index == ctx->composite_creds->inner.num_creds ||
+      *error != GRPC_ERROR_NONE) {
+    gpr_free(ctx);
+    return true;
+  }
+  // At least one inner cred is returning asynchronously, so we'll
+  // return asynchronously as well.
+  return false;
+}
+
+static void composite_call_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
+  for (size_t i = 0; i < c->inner.num_creds; ++i) {
+    grpc_call_credentials_cancel_get_request_metadata(
+        exec_ctx, c->inner.creds_array[i], md_array, GRPC_ERROR_REF(error));
+  }
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_call_credentials_vtable composite_call_credentials_vtable = {
-    composite_call_destruct, composite_call_get_request_metadata};
+    composite_call_destruct, composite_call_get_request_metadata,
+    composite_call_cancel_get_request_metadata};
 
 static grpc_call_credentials_array get_creds_array(
     grpc_call_credentials **creds_addr) {
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index b1f1e82..8a67c98 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -38,13 +38,10 @@
 /* -- Common. -- */
 
 grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
-    grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
-    void *user_data) {
+    grpc_call_credentials *creds) {
   grpc_credentials_metadata_request *r =
       gpr_zalloc(sizeof(grpc_credentials_metadata_request));
   r->creds = grpc_call_credentials_ref(creds);
-  r->cb = cb;
-  r->user_data = user_data;
   return r;
 }
 
@@ -104,18 +101,25 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-void grpc_call_credentials_get_request_metadata(
+bool grpc_call_credentials_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context context,
-    grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error) {
   if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
-    if (cb != NULL) {
-      cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
-    }
+    return true;
+  }
+  return creds->vtable->get_request_metadata(
+      exec_ctx, creds, pollent, context, md_array, on_request_metadata, error);
+}
+
+void grpc_call_credentials_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  if (creds == NULL || creds->vtable->cancel_get_request_metadata == NULL) {
     return;
   }
-  creds->vtable->get_request_metadata(exec_ctx, creds, pollent, context, cb,
-                                      user_data);
+  creds->vtable->cancel_get_request_metadata(exec_ctx, creds, md_array, error);
 }
 
 grpc_security_status grpc_channel_credentials_create_security_connector(
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index c45c2e9..04a54b0 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -138,48 +138,39 @@
 grpc_channel_credentials *grpc_channel_credentials_find_in_args(
     const grpc_channel_args *args);
 
-/* --- grpc_credentials_md. --- */
+/* --- grpc_credentials_mdelem_array. --- */
 
 typedef struct {
-  grpc_slice key;
-  grpc_slice value;
-} grpc_credentials_md;
+  grpc_mdelem *md;
+  size_t size;
+} grpc_credentials_mdelem_array;
 
-typedef struct {
-  grpc_credentials_md *entries;
-  size_t num_entries;
-  size_t allocated;
-  gpr_refcount refcount;
-} grpc_credentials_md_store;
+/// Takes a new ref to \a md.
+void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array *list,
+                                       grpc_mdelem md);
 
-grpc_credentials_md_store *grpc_credentials_md_store_create(
-    size_t initial_capacity);
+/// Appends all elements from \a src to \a dst, taking a new ref to each one.
+void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array *dst,
+                                          grpc_credentials_mdelem_array *src);
 
-/* Will ref key and value. */
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
-                                   grpc_slice key, grpc_slice value);
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
-                                            const char *key, const char *value);
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
-    grpc_credentials_md_store *store);
-void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_credentials_md_store *store);
+void grpc_credentials_mdelem_array_destroy(grpc_exec_ctx *exec_ctx,
+                                           grpc_credentials_mdelem_array *list);
 
 /* --- grpc_call_credentials. --- */
 
-/* error_details must be NULL if status is GRPC_CREDENTIALS_OK. */
-typedef void (*grpc_credentials_metadata_cb)(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details);
-
 typedef struct {
   void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_call_credentials *c);
-  void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
+  bool (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
                                grpc_call_credentials *c,
                                grpc_polling_entity *pollent,
                                grpc_auth_metadata_context context,
-                               grpc_credentials_metadata_cb cb,
-                               void *user_data);
+                               grpc_credentials_mdelem_array *md_array,
+                               grpc_closure *on_request_metadata,
+                               grpc_error **error);
+  void (*cancel_get_request_metadata)(grpc_exec_ctx *exec_ctx,
+                                      grpc_call_credentials *c,
+                                      grpc_credentials_mdelem_array *md_array,
+                                      grpc_error *error);
 } grpc_call_credentials_vtable;
 
 struct grpc_call_credentials {
@@ -191,15 +182,29 @@
 grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
 void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx,
                                  grpc_call_credentials *creds);
-void grpc_call_credentials_get_request_metadata(
+
+/// Returns true if completed synchronously, in which case \a error will
+/// be set to indicate the result.  Otherwise, \a on_request_metadata will
+/// be invoked asynchronously when complete.  \a md_array will be populated
+/// with the resulting metadata once complete.
+bool grpc_call_credentials_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context context,
-    grpc_credentials_metadata_cb cb, void *user_data);
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error);
+
+/// Cancels a pending asynchronous operation started by
+/// grpc_call_credentials_get_request_metadata() with the corresponding
+/// value of \a md_array.
+void grpc_call_credentials_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error);
 
 /* Metadata-only credentials with the specified key and value where
    asynchronicity can be simulated for testing. */
 grpc_call_credentials *grpc_md_only_test_credentials_create(
-    const char *md_key, const char *md_value, int is_async);
+    grpc_exec_ctx *exec_ctx, const char *md_key, const char *md_value,
+    bool is_async);
 
 /* --- grpc_server_credentials. --- */
 
@@ -238,14 +243,11 @@
 
 typedef struct {
   grpc_call_credentials *creds;
-  grpc_credentials_metadata_cb cb;
   grpc_http_response response;
-  void *user_data;
 } grpc_credentials_metadata_request;
 
 grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
-    grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
-    void *user_data);
+    grpc_call_credentials *creds);
 
 void grpc_credentials_metadata_request_destroy(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r);
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
index fcfdd52..ccd39e6 100644
--- a/src/core/lib/security/credentials/credentials_metadata.c
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -24,65 +24,36 @@
 
 #include "src/core/lib/slice/slice_internal.h"
 
-static void store_ensure_capacity(grpc_credentials_md_store *store) {
-  if (store->num_entries == store->allocated) {
-    store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
-    store->entries = gpr_realloc(
-        store->entries, store->allocated * sizeof(grpc_credentials_md));
+static void mdelem_list_ensure_capacity(grpc_credentials_mdelem_array *list,
+                                        size_t additional_space_needed) {
+  size_t target_size = list->size + additional_space_needed;
+  // Find the next power of two greater than the target size (i.e.,
+  // whenever we add more space, we double what we already have).
+  size_t new_size = 2;
+  while (new_size < target_size) {
+    new_size *= 2;
+  }
+  list->md = gpr_realloc(list->md, sizeof(grpc_mdelem) * new_size);
+}
+
+void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array *list,
+                                       grpc_mdelem md) {
+  mdelem_list_ensure_capacity(list, 1);
+  list->md[list->size++] = GRPC_MDELEM_REF(md);
+}
+
+void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array *dst,
+                                          grpc_credentials_mdelem_array *src) {
+  mdelem_list_ensure_capacity(dst, src->size);
+  for (size_t i = 0; i < src->size; ++i) {
+    dst->md[dst->size++] = GRPC_MDELEM_REF(src->md[i]);
   }
 }
 
-grpc_credentials_md_store *grpc_credentials_md_store_create(
-    size_t initial_capacity) {
-  grpc_credentials_md_store *store =
-      gpr_zalloc(sizeof(grpc_credentials_md_store));
-  if (initial_capacity > 0) {
-    store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
-    store->allocated = initial_capacity;
+void grpc_credentials_mdelem_array_destroy(
+    grpc_exec_ctx *exec_ctx, grpc_credentials_mdelem_array *list) {
+  for (size_t i = 0; i < list->size; ++i) {
+    GRPC_MDELEM_UNREF(exec_ctx, list->md[i]);
   }
-  gpr_ref_init(&store->refcount, 1);
-  return store;
-}
-
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
-                                   grpc_slice key, grpc_slice value) {
-  if (store == NULL) return;
-  store_ensure_capacity(store);
-  store->entries[store->num_entries].key = grpc_slice_ref_internal(key);
-  store->entries[store->num_entries].value = grpc_slice_ref_internal(value);
-  store->num_entries++;
-}
-
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
-                                            const char *key,
-                                            const char *value) {
-  if (store == NULL) return;
-  store_ensure_capacity(store);
-  store->entries[store->num_entries].key = grpc_slice_from_copied_string(key);
-  store->entries[store->num_entries].value =
-      grpc_slice_from_copied_string(value);
-  store->num_entries++;
-}
-
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
-    grpc_credentials_md_store *store) {
-  if (store == NULL) return NULL;
-  gpr_ref(&store->refcount);
-  return store;
-}
-
-void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_credentials_md_store *store) {
-  if (store == NULL) return;
-  if (gpr_unref(&store->refcount)) {
-    if (store->entries != NULL) {
-      size_t i;
-      for (i = 0; i < store->num_entries; i++) {
-        grpc_slice_unref_internal(exec_ctx, store->entries[i].key);
-        grpc_slice_unref_internal(exec_ctx, store->entries[i].value);
-      }
-      gpr_free(store->entries);
-    }
-    gpr_free(store);
-  }
+  gpr_free(list->md);
 }
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index 67e74f7..ac90178 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -98,49 +98,44 @@
 static void md_only_test_destruct(grpc_exec_ctx *exec_ctx,
                                   grpc_call_credentials *creds) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
-  grpc_credentials_md_store_unref(exec_ctx, c->md_store);
+  GRPC_MDELEM_UNREF(exec_ctx, c->md);
 }
 
-static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
-                                          void *user_data, grpc_error *error) {
-  grpc_credentials_metadata_request *r =
-      (grpc_credentials_metadata_request *)user_data;
-  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
-  r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
-        GRPC_CREDENTIALS_OK, NULL);
-  grpc_credentials_metadata_request_destroy(exec_ctx, r);
-}
-
-static void md_only_test_get_request_metadata(
+static bool md_only_test_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context context,
-    grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
-
+  grpc_credentials_mdelem_array_add(md_array, c->md);
   if (c->is_async) {
-    grpc_credentials_metadata_request *cb_arg =
-        grpc_credentials_metadata_request_create(creds, cb, user_data);
-    GRPC_CLOSURE_SCHED(exec_ctx,
-                       GRPC_CLOSURE_CREATE(on_simulated_token_fetch_done,
-                                           cb_arg, grpc_executor_scheduler),
-                       GRPC_ERROR_NONE);
-  } else {
-    cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK, NULL);
+    GRPC_CLOSURE_SCHED(exec_ctx, on_request_metadata, GRPC_ERROR_NONE);
+    return false;
   }
+  return true;
+}
+
+static void md_only_test_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_call_credentials_vtable md_only_test_vtable = {
-    md_only_test_destruct, md_only_test_get_request_metadata};
+    md_only_test_destruct, md_only_test_get_request_metadata,
+    md_only_test_cancel_get_request_metadata};
 
 grpc_call_credentials *grpc_md_only_test_credentials_create(
-    const char *md_key, const char *md_value, int is_async) {
+    grpc_exec_ctx *exec_ctx, const char *md_key, const char *md_value,
+    bool is_async) {
   grpc_md_only_test_credentials *c =
       gpr_zalloc(sizeof(grpc_md_only_test_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &md_only_test_vtable;
   gpr_ref_init(&c->base.refcount, 1);
-  c->md_store = grpc_credentials_md_store_create(1);
-  grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
+  c->md =
+      grpc_mdelem_from_slices(exec_ctx, grpc_slice_from_copied_string(md_key),
+                              grpc_slice_from_copied_string(md_value));
   c->is_async = is_async;
   return &c->base;
 }
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
index fae7a6a..aa0f3b6 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.h
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -52,8 +52,8 @@
 
 typedef struct {
   grpc_call_credentials base;
-  grpc_credentials_md_store *md_store;
-  int is_async;
+  grpc_mdelem md;
+  bool is_async;
 } grpc_md_only_test_credentials;
 
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
index 4b32c5a..3de8319 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.c
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -30,26 +30,33 @@
 static void iam_destruct(grpc_exec_ctx *exec_ctx,
                          grpc_call_credentials *creds) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
-  grpc_credentials_md_store_unref(exec_ctx, c->iam_md);
+  grpc_credentials_mdelem_array_destroy(exec_ctx, &c->md_array);
 }
 
-static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_polling_entity *pollent,
                                      grpc_auth_metadata_context context,
-                                     grpc_credentials_metadata_cb cb,
-                                     void *user_data) {
+                                     grpc_credentials_mdelem_array *md_array,
+                                     grpc_closure *on_request_metadata,
+                                     grpc_error **error) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
-  cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
-     GRPC_CREDENTIALS_OK, NULL);
+  grpc_credentials_mdelem_array_append(md_array, &c->md_array);
+  return true;
 }
 
-static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
-                                                  iam_get_request_metadata};
+static void iam_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
+}
+
+static grpc_call_credentials_vtable iam_vtable = {
+    iam_destruct, iam_get_request_metadata, iam_cancel_get_request_metadata};
 
 grpc_call_credentials *grpc_google_iam_credentials_create(
     const char *token, const char *authority_selector, void *reserved) {
-  grpc_google_iam_credentials *c;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   GRPC_API_TRACE(
       "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
       "reserved=%p)",
@@ -57,14 +64,22 @@
   GPR_ASSERT(reserved == NULL);
   GPR_ASSERT(token != NULL);
   GPR_ASSERT(authority_selector != NULL);
-  c = gpr_zalloc(sizeof(grpc_google_iam_credentials));
+  grpc_google_iam_credentials *c = gpr_zalloc(sizeof(*c));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
   c->base.vtable = &iam_vtable;
   gpr_ref_init(&c->base.refcount, 1);
-  c->iam_md = grpc_credentials_md_store_create(2);
-  grpc_credentials_md_store_add_cstrings(
-      c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
-  grpc_credentials_md_store_add_cstrings(
-      c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
+  grpc_mdelem md = grpc_mdelem_from_slices(
+      &exec_ctx,
+      grpc_slice_from_static_string(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY),
+      grpc_slice_from_copied_string(token));
+  grpc_credentials_mdelem_array_add(&c->md_array, md);
+  GRPC_MDELEM_UNREF(&exec_ctx, md);
+  md = grpc_mdelem_from_slices(
+      &exec_ctx,
+      grpc_slice_from_static_string(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY),
+      grpc_slice_from_copied_string(authority_selector));
+  grpc_credentials_mdelem_array_add(&c->md_array, md);
+  GRPC_MDELEM_UNREF(&exec_ctx, md);
+  grpc_exec_ctx_finish(&exec_ctx);
   return &c->base;
 }
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h
index fff3c6d..5e3cf65 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.h
+++ b/src/core/lib/security/credentials/iam/iam_credentials.h
@@ -23,7 +23,7 @@
 
 typedef struct {
   grpc_call_credentials base;
-  grpc_credentials_md_store *iam_md;
+  grpc_credentials_mdelem_array md_array;
 } grpc_google_iam_credentials;
 
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
index 589a6f9..02c82e9 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.c
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -29,10 +29,8 @@
 
 static void jwt_reset_cache(grpc_exec_ctx *exec_ctx,
                             grpc_service_account_jwt_access_credentials *c) {
-  if (c->cached.jwt_md != NULL) {
-    grpc_credentials_md_store_unref(exec_ctx, c->cached.jwt_md);
-    c->cached.jwt_md = NULL;
-  }
+  GRPC_MDELEM_UNREF(exec_ctx, c->cached.jwt_md);
+  c->cached.jwt_md = GRPC_MDNULL;
   if (c->cached.service_url != NULL) {
     gpr_free(c->cached.service_url);
     c->cached.service_url = NULL;
@@ -49,33 +47,34 @@
   gpr_mu_destroy(&c->cache_mu);
 }
 
-static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_polling_entity *pollent,
                                      grpc_auth_metadata_context context,
-                                     grpc_credentials_metadata_cb cb,
-                                     void *user_data) {
+                                     grpc_credentials_mdelem_array *md_array,
+                                     grpc_closure *on_request_metadata,
+                                     grpc_error **error) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   gpr_timespec refresh_threshold = gpr_time_from_seconds(
       GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
 
   /* See if we can return a cached jwt. */
-  grpc_credentials_md_store *jwt_md = NULL;
+  grpc_mdelem jwt_md = GRPC_MDNULL;
   {
     gpr_mu_lock(&c->cache_mu);
     if (c->cached.service_url != NULL &&
         strcmp(c->cached.service_url, context.service_url) == 0 &&
-        c->cached.jwt_md != NULL &&
+        !GRPC_MDISNULL(c->cached.jwt_md) &&
         (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
                                    gpr_now(GPR_CLOCK_REALTIME)),
                       refresh_threshold) > 0)) {
-      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+      jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md);
     }
     gpr_mu_unlock(&c->cache_mu);
   }
 
-  if (jwt_md == NULL) {
+  if (GRPC_MDISNULL(jwt_md)) {
     char *jwt = NULL;
     /* Generate a new jwt. */
     gpr_mu_lock(&c->cache_mu);
@@ -89,27 +88,33 @@
       c->cached.jwt_expiration =
           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
       c->cached.service_url = gpr_strdup(context.service_url);
-      c->cached.jwt_md = grpc_credentials_md_store_create(1);
-      grpc_credentials_md_store_add_cstrings(
-          c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
+      c->cached.jwt_md = grpc_mdelem_from_slices(
+          exec_ctx,
+          grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+          grpc_slice_from_copied_string(md_value));
       gpr_free(md_value);
-      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+      jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md);
     }
     gpr_mu_unlock(&c->cache_mu);
   }
 
-  if (jwt_md != NULL) {
-    cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
-       GRPC_CREDENTIALS_OK, NULL);
-    grpc_credentials_md_store_unref(exec_ctx, jwt_md);
+  if (!GRPC_MDISNULL(jwt_md)) {
+    grpc_credentials_mdelem_array_add(md_array, jwt_md);
+    GRPC_MDELEM_UNREF(exec_ctx, jwt_md);
   } else {
-    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
-       "Could not generate JWT.");
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT.");
   }
+  return true;
 }
 
-static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
-                                                  jwt_get_request_metadata};
+static void jwt_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
+}
+
+static grpc_call_credentials_vtable jwt_vtable = {
+    jwt_destruct, jwt_get_request_metadata, jwt_cancel_get_request_metadata};
 
 grpc_call_credentials *
 grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
@@ -125,6 +130,13 @@
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &jwt_vtable;
   c->key = key;
+  gpr_timespec max_token_lifetime = grpc_max_auth_token_lifetime();
+  if (gpr_time_cmp(token_lifetime, max_token_lifetime) > 0) {
+    gpr_log(GPR_INFO,
+            "Cropping token lifetime to maximum allowed value (%d secs).",
+            (int)max_token_lifetime.tv_sec);
+    token_lifetime = grpc_max_auth_token_lifetime();
+  }
   c->jwt_lifetime = token_lifetime;
   gpr_mu_init(&c->cache_mu);
   jwt_reset_cache(exec_ctx, c);
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
index 6e461f1..07f4022 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.h
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -29,7 +29,7 @@
   // the service_url for a more sophisticated one.
   gpr_mu cache_mu;
   struct {
-    grpc_credentials_md_store *jwt_md;
+    grpc_mdelem jwt_md;
     char *service_url;
     gpr_timespec jwt_expiration;
   } cached;
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 9de561b..ffa941b 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -107,7 +107,7 @@
                                           grpc_call_credentials *creds) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
-  grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
+  GRPC_MDELEM_UNREF(exec_ctx, c->access_token_md);
   gpr_mu_destroy(&c->mu);
   grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context);
 }
@@ -115,7 +115,7 @@
 grpc_credentials_status
 grpc_oauth2_token_fetcher_credentials_parse_server_response(
     grpc_exec_ctx *exec_ctx, const grpc_http_response *response,
-    grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime) {
+    grpc_mdelem *token_md, gpr_timespec *token_lifetime) {
   char *null_terminated_body = NULL;
   char *new_access_token = NULL;
   grpc_credentials_status status = GRPC_CREDENTIALS_OK;
@@ -184,17 +184,18 @@
     token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
     token_lifetime->tv_nsec = 0;
     token_lifetime->clock_type = GPR_TIMESPAN;
-    if (*token_md != NULL) grpc_credentials_md_store_unref(exec_ctx, *token_md);
-    *token_md = grpc_credentials_md_store_create(1);
-    grpc_credentials_md_store_add_cstrings(
-        *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
+    if (!GRPC_MDISNULL(*token_md)) GRPC_MDELEM_UNREF(exec_ctx, *token_md);
+    *token_md = grpc_mdelem_from_slices(
+        exec_ctx,
+        grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+        grpc_slice_from_copied_string(new_access_token));
     status = GRPC_CREDENTIALS_OK;
   }
 
 end:
-  if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
-    grpc_credentials_md_store_unref(exec_ctx, *token_md);
-    *token_md = NULL;
+  if (status != GRPC_CREDENTIALS_OK && !GRPC_MDISNULL(*token_md)) {
+    GRPC_MDELEM_UNREF(exec_ctx, *token_md);
+    *token_md = GRPC_MDNULL;
   }
   if (null_terminated_body != NULL) gpr_free(null_terminated_body);
   if (new_access_token != NULL) gpr_free(new_access_token);
@@ -205,63 +206,124 @@
 static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
                                                   void *user_data,
                                                   grpc_error *error) {
+  GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
   grpc_credentials_metadata_request *r =
       (grpc_credentials_metadata_request *)user_data;
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)r->creds;
+  grpc_mdelem access_token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
-  grpc_credentials_status status;
-
-  GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
-
+  grpc_credentials_status status =
+      grpc_oauth2_token_fetcher_credentials_parse_server_response(
+          exec_ctx, &r->response, &access_token_md, &token_lifetime);
+  // Update cache and grab list of pending requests.
   gpr_mu_lock(&c->mu);
-  status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
-      exec_ctx, &r->response, &c->access_token_md, &token_lifetime);
-  if (status == GRPC_CREDENTIALS_OK) {
-    c->token_expiration =
-        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
-    r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
-          c->access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL);
-  } else {
-    c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
-    r->cb(exec_ctx, r->user_data, NULL, 0, status,
-          "Error occured when fetching oauth2 token.");
-  }
+  c->token_fetch_pending = false;
+  c->access_token_md = GRPC_MDELEM_REF(access_token_md);
+  c->token_expiration =
+      status == GRPC_CREDENTIALS_OK
+          ? gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime)
+          : gpr_inf_past(GPR_CLOCK_REALTIME);
+  grpc_oauth2_pending_get_request_metadata *pending_request =
+      c->pending_requests;
+  c->pending_requests = NULL;
   gpr_mu_unlock(&c->mu);
+  // Invoke callbacks for all pending requests.
+  while (pending_request != NULL) {
+    if (status == GRPC_CREDENTIALS_OK) {
+      grpc_credentials_mdelem_array_add(pending_request->md_array,
+                                        access_token_md);
+    } else {
+      error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+          "Error occured when fetching oauth2 token.", &error, 1);
+    }
+    GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata, error);
+    grpc_oauth2_pending_get_request_metadata *prev = pending_request;
+    pending_request = pending_request->next;
+    gpr_free(prev);
+  }
+  GRPC_MDELEM_UNREF(exec_ctx, access_token_md);
+  grpc_call_credentials_unref(exec_ctx, r->creds);
   grpc_credentials_metadata_request_destroy(exec_ctx, r);
 }
 
-static void oauth2_token_fetcher_get_request_metadata(
+static bool oauth2_token_fetcher_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context context,
-    grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
+  // Check if we can use the cached token.
   gpr_timespec refresh_threshold = gpr_time_from_seconds(
       GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
-  grpc_credentials_md_store *cached_access_token_md = NULL;
-  {
-    gpr_mu_lock(&c->mu);
-    if (c->access_token_md != NULL &&
-        (gpr_time_cmp(
-             gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
-             refresh_threshold) > 0)) {
-      cached_access_token_md =
-          grpc_credentials_md_store_ref(c->access_token_md);
-    }
+  grpc_mdelem cached_access_token_md = GRPC_MDNULL;
+  gpr_mu_lock(&c->mu);
+  if (!GRPC_MDISNULL(c->access_token_md) &&
+      (gpr_time_cmp(
+           gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
+           refresh_threshold) > 0)) {
+    cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md);
+  }
+  if (!GRPC_MDISNULL(cached_access_token_md)) {
     gpr_mu_unlock(&c->mu);
+    grpc_credentials_mdelem_array_add(md_array, cached_access_token_md);
+    GRPC_MDELEM_UNREF(exec_ctx, cached_access_token_md);
+    return true;
   }
-  if (cached_access_token_md != NULL) {
-    cb(exec_ctx, user_data, cached_access_token_md->entries,
-       cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL);
-    grpc_credentials_md_store_unref(exec_ctx, cached_access_token_md);
-  } else {
-    c->fetch_func(
-        exec_ctx,
-        grpc_credentials_metadata_request_create(creds, cb, user_data),
-        &c->httpcli_context, pollent, on_oauth2_token_fetcher_http_response,
-        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
+  // Couldn't get the token from the cache.
+  // Add request to c->pending_requests and start a new fetch if needed.
+  grpc_oauth2_pending_get_request_metadata *pending_request =
+      (grpc_oauth2_pending_get_request_metadata *)gpr_malloc(
+          sizeof(*pending_request));
+  pending_request->md_array = md_array;
+  pending_request->on_request_metadata = on_request_metadata;
+  pending_request->next = c->pending_requests;
+  c->pending_requests = pending_request;
+  bool start_fetch = false;
+  if (!c->token_fetch_pending) {
+    c->token_fetch_pending = true;
+    start_fetch = true;
   }
+  gpr_mu_unlock(&c->mu);
+  if (start_fetch) {
+    grpc_call_credentials_ref(creds);
+    c->fetch_func(exec_ctx, grpc_credentials_metadata_request_create(creds),
+                  &c->httpcli_context, pollent,
+                  on_oauth2_token_fetcher_http_response,
+                  gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
+  }
+  return false;
+}
+
+static void oauth2_token_fetcher_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  grpc_oauth2_token_fetcher_credentials *c =
+      (grpc_oauth2_token_fetcher_credentials *)creds;
+  gpr_mu_lock(&c->mu);
+  grpc_oauth2_pending_get_request_metadata *prev = NULL;
+  grpc_oauth2_pending_get_request_metadata *pending_request =
+      c->pending_requests;
+  while (pending_request != NULL) {
+    if (pending_request->md_array == md_array) {
+      // Remove matching pending request from the list.
+      if (prev != NULL) {
+        prev->next = pending_request->next;
+      } else {
+        c->pending_requests = pending_request->next;
+      }
+      // Invoke the callback immediately with an error.
+      GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata,
+                         GRPC_ERROR_REF(error));
+      gpr_free(pending_request);
+      break;
+    }
+    prev = pending_request;
+    pending_request = pending_request->next;
+  }
+  gpr_mu_unlock(&c->mu);
+  GRPC_ERROR_UNREF(error);
 }
 
 static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
@@ -280,7 +342,8 @@
 //
 
 static grpc_call_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata,
+    oauth2_token_fetcher_cancel_get_request_metadata};
 
 static void compute_engine_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -301,7 +364,6 @@
   grpc_httpcli_get(
       exec_ctx, httpcli_context, pollent, resource_quota, &request, deadline,
       GRPC_CLOSURE_CREATE(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
-
       &metadata_req->response);
   grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
 }
@@ -331,7 +393,8 @@
 }
 
 static grpc_call_credentials_vtable refresh_token_vtable = {
-    refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
+    refresh_token_destruct, oauth2_token_fetcher_get_request_metadata,
+    oauth2_token_fetcher_cancel_get_request_metadata};
 
 static void refresh_token_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -416,26 +479,33 @@
 static void access_token_destruct(grpc_exec_ctx *exec_ctx,
                                   grpc_call_credentials *creds) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
-  grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
+  GRPC_MDELEM_UNREF(exec_ctx, c->access_token_md);
 }
 
-static void access_token_get_request_metadata(
+static bool access_token_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
     grpc_polling_entity *pollent, grpc_auth_metadata_context context,
-    grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+    grpc_error **error) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
-  cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK,
-     NULL);
+  grpc_credentials_mdelem_array_add(md_array, c->access_token_md);
+  return true;
+}
+
+static void access_token_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_call_credentials_vtable access_token_vtable = {
-    access_token_destruct, access_token_get_request_metadata};
+    access_token_destruct, access_token_get_request_metadata,
+    access_token_cancel_get_request_metadata};
 
 grpc_call_credentials *grpc_access_token_credentials_create(
     const char *access_token, void *reserved) {
   grpc_access_token_credentials *c =
       gpr_zalloc(sizeof(grpc_access_token_credentials));
-  char *token_md_value;
   GRPC_API_TRACE(
       "grpc_access_token_credentials_create(access_token=<redacted>, "
       "reserved=%p)",
@@ -444,10 +514,13 @@
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &access_token_vtable;
   gpr_ref_init(&c->base.refcount, 1);
-  c->access_token_md = grpc_credentials_md_store_create(1);
+  char *token_md_value;
   gpr_asprintf(&token_md_value, "Bearer %s", access_token);
-  grpc_credentials_md_store_add_cstrings(
-      c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  c->access_token_md = grpc_mdelem_from_slices(
+      &exec_ctx, grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+      grpc_slice_from_copied_string(token_md_value));
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(token_md_value);
   return &c->base;
 }
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 72093af..9d041a2 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -58,11 +58,20 @@
                                        grpc_polling_entity *pollent,
                                        grpc_iomgr_cb_func cb,
                                        gpr_timespec deadline);
+
+typedef struct grpc_oauth2_pending_get_request_metadata {
+  grpc_credentials_mdelem_array *md_array;
+  grpc_closure *on_request_metadata;
+  struct grpc_oauth2_pending_get_request_metadata *next;
+} grpc_oauth2_pending_get_request_metadata;
+
 typedef struct {
   grpc_call_credentials base;
   gpr_mu mu;
-  grpc_credentials_md_store *access_token_md;
+  grpc_mdelem access_token_md;
   gpr_timespec token_expiration;
+  bool token_fetch_pending;
+  grpc_oauth2_pending_get_request_metadata *pending_requests;
   grpc_httpcli_context httpcli_context;
   grpc_fetch_oauth2_func fetch_func;
 } grpc_oauth2_token_fetcher_credentials;
@@ -76,7 +85,7 @@
 // Access token credentials.
 typedef struct {
   grpc_call_credentials base;
-  grpc_credentials_md_store *access_token_md;
+  grpc_mdelem access_token_md;
 } grpc_access_token_credentials;
 
 // Private constructor for refresh token credentials from an already parsed
@@ -89,6 +98,6 @@
 grpc_credentials_status
 grpc_oauth2_token_fetcher_credentials_parse_server_response(
     grpc_exec_ctx *exec_ctx, const struct grpc_http_response *response,
-    grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
+    grpc_mdelem *token_md, gpr_timespec *token_lifetime);
 
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index 96ebfb4..73e0c23 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -31,19 +31,28 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/validate_metadata.h"
 
-typedef struct {
-  void *user_data;
-  grpc_credentials_metadata_cb cb;
-} grpc_metadata_plugin_request;
-
 static void plugin_destruct(grpc_exec_ctx *exec_ctx,
                             grpc_call_credentials *creds) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+  gpr_mu_destroy(&c->mu);
   if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
     c->plugin.destroy(c->plugin.state);
   }
 }
 
+static void pending_request_remove_locked(
+    grpc_plugin_credentials *c,
+    grpc_plugin_credentials_pending_request *pending_request) {
+  if (pending_request->prev == NULL) {
+    c->pending_requests = pending_request->next;
+  } else {
+    pending_request->prev->next = pending_request->next;
+  }
+  if (pending_request->next != NULL) {
+    pending_request->next->prev = pending_request->prev;
+  }
+}
+
 static void plugin_md_request_metadata_ready(void *request,
                                              const grpc_metadata *md,
                                              size_t num_md,
@@ -53,76 +62,117 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(
       GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP,
       NULL, NULL);
-  grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
-  if (status != GRPC_STATUS_OK) {
-    if (error_details != NULL) {
-      gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
-              error_details);
-    }
-    r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
-          error_details);
-  } else {
-    size_t i;
-    bool seen_illegal_header = false;
-    grpc_credentials_md *md_array = NULL;
-    for (i = 0; i < num_md; i++) {
-      if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
-                             grpc_validate_header_key_is_legal(md[i].key))) {
-        seen_illegal_header = true;
-        break;
-      } else if (!grpc_is_binary_header(md[i].key) &&
-                 !GRPC_LOG_IF_ERROR(
-                     "validate_metadata_from_plugin",
-                     grpc_validate_header_nonbin_value_is_legal(md[i].value))) {
-        gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
-        seen_illegal_header = true;
-        break;
+  grpc_plugin_credentials_pending_request *r =
+      (grpc_plugin_credentials_pending_request *)request;
+  // Check if the request has been cancelled.
+  // If not, remove it from the pending list, so that it cannot be
+  // cancelled out from under us.
+  gpr_mu_lock(&r->creds->mu);
+  if (!r->cancelled) pending_request_remove_locked(r->creds, r);
+  gpr_mu_unlock(&r->creds->mu);
+  grpc_call_credentials_unref(&exec_ctx, &r->creds->base);
+  // If it has not been cancelled, process it.
+  if (!r->cancelled) {
+    if (status != GRPC_STATUS_OK) {
+      char *msg;
+      gpr_asprintf(&msg, "Getting metadata from plugin failed with error: %s",
+                   error_details);
+      GRPC_CLOSURE_SCHED(&exec_ctx, r->on_request_metadata,
+                         GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
+      gpr_free(msg);
+    } else {
+      bool seen_illegal_header = false;
+      for (size_t i = 0; i < num_md; ++i) {
+        if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
+                               grpc_validate_header_key_is_legal(md[i].key))) {
+          seen_illegal_header = true;
+          break;
+        } else if (!grpc_is_binary_header(md[i].key) &&
+                   !GRPC_LOG_IF_ERROR(
+                       "validate_metadata_from_plugin",
+                       grpc_validate_header_nonbin_value_is_legal(
+                           md[i].value))) {
+          gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
+          seen_illegal_header = true;
+          break;
+        }
       }
-    }
-    if (seen_illegal_header) {
-      r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
-            "Illegal metadata");
-    } else if (num_md > 0) {
-      md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
-      for (i = 0; i < num_md; i++) {
-        md_array[i].key = grpc_slice_ref_internal(md[i].key);
-        md_array[i].value = grpc_slice_ref_internal(md[i].value);
+      if (seen_illegal_header) {
+        GRPC_CLOSURE_SCHED(
+            &exec_ctx, r->on_request_metadata,
+            GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal metadata"));
+      } else {
+        for (size_t i = 0; i < num_md; ++i) {
+          grpc_mdelem mdelem = grpc_mdelem_from_slices(
+              &exec_ctx, grpc_slice_ref_internal(md[i].key),
+              grpc_slice_ref_internal(md[i].value));
+          grpc_credentials_mdelem_array_add(r->md_array, mdelem);
+          GRPC_MDELEM_UNREF(&exec_ctx, mdelem);
+        }
+        GRPC_CLOSURE_SCHED(&exec_ctx, r->on_request_metadata, GRPC_ERROR_NONE);
       }
-      r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
-            NULL);
-      for (i = 0; i < num_md; i++) {
-        grpc_slice_unref_internal(&exec_ctx, md_array[i].key);
-        grpc_slice_unref_internal(&exec_ctx, md_array[i].value);
-      }
-      gpr_free(md_array);
-    } else if (num_md == 0) {
-      r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
     }
   }
   gpr_free(r);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                         grpc_call_credentials *creds,
                                         grpc_polling_entity *pollent,
                                         grpc_auth_metadata_context context,
-                                        grpc_credentials_metadata_cb cb,
-                                        void *user_data) {
+                                        grpc_credentials_mdelem_array *md_array,
+                                        grpc_closure *on_request_metadata,
+                                        grpc_error **error) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
   if (c->plugin.get_metadata != NULL) {
-    grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request));
-    request->user_data = user_data;
-    request->cb = cb;
+    // Create pending_request object.
+    grpc_plugin_credentials_pending_request *pending_request =
+        (grpc_plugin_credentials_pending_request *)gpr_zalloc(
+            sizeof(*pending_request));
+    pending_request->creds = c;
+    pending_request->md_array = md_array;
+    pending_request->on_request_metadata = on_request_metadata;
+    // Add it to the pending list.
+    gpr_mu_lock(&c->mu);
+    if (c->pending_requests != NULL) {
+      c->pending_requests->prev = pending_request;
+    }
+    pending_request->next = c->pending_requests;
+    c->pending_requests = pending_request;
+    gpr_mu_unlock(&c->mu);
+    // Invoke the plugin.  The callback holds a ref to us.
+    grpc_call_credentials_ref(creds);
     c->plugin.get_metadata(c->plugin.state, context,
-                           plugin_md_request_metadata_ready, request);
-  } else {
-    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
+                           plugin_md_request_metadata_ready, pending_request);
+    return false;
   }
+  return true;
+}
+
+static void plugin_cancel_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+  grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+  gpr_mu_lock(&c->mu);
+  for (grpc_plugin_credentials_pending_request *pending_request =
+           c->pending_requests;
+       pending_request != NULL; pending_request = pending_request->next) {
+    if (pending_request->md_array == md_array) {
+      pending_request->cancelled = true;
+      GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata,
+                         GRPC_ERROR_REF(error));
+      pending_request_remove_locked(c, pending_request);
+      break;
+    }
+  }
+  gpr_mu_unlock(&c->mu);
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_call_credentials_vtable plugin_vtable = {
-    plugin_destruct, plugin_get_request_metadata};
+    plugin_destruct, plugin_get_request_metadata,
+    plugin_cancel_get_request_metadata};
 
 grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
     grpc_metadata_credentials_plugin plugin, void *reserved) {
@@ -134,5 +184,6 @@
   c->base.vtable = &plugin_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->plugin = plugin;
+  gpr_mu_init(&c->mu);
   return &c->base;
 }
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h
index ba3dd76..57266d5 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.h
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h
@@ -21,10 +21,22 @@
 
 #include "src/core/lib/security/credentials/credentials.h"
 
-typedef struct {
+struct grpc_plugin_credentials;
+
+typedef struct grpc_plugin_credentials_pending_request {
+  bool cancelled;
+  struct grpc_plugin_credentials *creds;
+  grpc_credentials_mdelem_array *md_array;
+  grpc_closure *on_request_metadata;
+  struct grpc_plugin_credentials_pending_request *prev;
+  struct grpc_plugin_credentials_pending_request *next;
+} grpc_plugin_credentials_pending_request;
+
+typedef struct grpc_plugin_credentials {
   grpc_call_credentials base;
   grpc_metadata_credentials_plugin plugin;
-  grpc_credentials_md_store *plugin_md;
+  gpr_mu mu;
+  grpc_plugin_credentials_pending_request *pending_requests;
 } grpc_plugin_credentials;
 
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index 50a51b3..531a884 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -51,8 +51,15 @@
   grpc_polling_entity *pollent;
   gpr_atm security_context_set;
   gpr_mu security_context_mu;
+  grpc_credentials_mdelem_array md_array;
   grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
   grpc_auth_metadata_context auth_md_context;
+  grpc_closure closure;
+  // Either 0 (no cancellation and no async operation in flight),
+  // a grpc_closure* (if the lowest bit is 0),
+  // or a grpc_error* (if the lowest bit is 1).
+  gpr_atm cancellation_state;
+  grpc_closure cancel_closure;
 } call_data;
 
 /* We can have a per-channel credentials. */
@@ -61,6 +68,43 @@
   grpc_auth_context *auth_context;
 } channel_data;
 
+static void decode_cancel_state(gpr_atm cancel_state, grpc_closure **func,
+                                grpc_error **error) {
+  // If the lowest bit is 1, the value is a grpc_error*.
+  // Otherwise, if non-zdero, the value is a grpc_closure*.
+  if (cancel_state & 1) {
+    *error = (grpc_error *)(cancel_state & ~(gpr_atm)1);
+  } else if (cancel_state != 0) {
+    *func = (grpc_closure *)cancel_state;
+  }
+}
+
+static gpr_atm encode_cancel_state_error(grpc_error *error) {
+  // Set the lowest bit to 1 to indicate that it's an error.
+  return (gpr_atm)1 | (gpr_atm)error;
+}
+
+// Returns an error if the call has been cancelled.  Otherwise, sets the
+// cancellation function to be called upon cancellation.
+static grpc_error *set_cancel_func(grpc_call_element *elem,
+                                   grpc_iomgr_cb_func func) {
+  call_data *calld = (call_data *)elem->call_data;
+  // Decode original state.
+  gpr_atm original_state = gpr_atm_acq_load(&calld->cancellation_state);
+  grpc_error *original_error = GRPC_ERROR_NONE;
+  grpc_closure *original_func = NULL;
+  decode_cancel_state(original_state, &original_func, &original_error);
+  // If error is set, return it.
+  if (original_error != GRPC_ERROR_NONE) return GRPC_ERROR_REF(original_error);
+  // Otherwise, store func.
+  GRPC_CLOSURE_INIT(&calld->cancel_closure, func, elem,
+                    grpc_schedule_on_exec_ctx);
+  GPR_ASSERT(((gpr_atm)&calld->cancel_closure & (gpr_atm)1) == 0);
+  gpr_atm_rel_store(&calld->cancellation_state,
+                    (gpr_atm)&calld->cancel_closure);
+  return GRPC_ERROR_NONE;
+}
+
 static void reset_auth_metadata_context(
     grpc_auth_metadata_context *auth_md_context) {
   if (auth_md_context->service_url != NULL) {
@@ -86,41 +130,29 @@
   *combined = grpc_error_add_child(*combined, error);
 }
 
-static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
-                                    grpc_credentials_md *md_elems,
-                                    size_t num_md,
-                                    grpc_credentials_status status,
-                                    const char *error_details) {
-  grpc_transport_stream_op_batch *batch =
-      (grpc_transport_stream_op_batch *)user_data;
+static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *arg,
+                                    grpc_error *input_error) {
+  grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
   grpc_call_element *elem = batch->handler_private.extra_arg;
   call_data *calld = elem->call_data;
   reset_auth_metadata_context(&calld->auth_md_context);
-  grpc_error *error = GRPC_ERROR_NONE;
-  if (status != GRPC_CREDENTIALS_OK) {
-    error = grpc_error_set_int(
-        GRPC_ERROR_CREATE_FROM_COPIED_STRING(
-            error_details != NULL && strlen(error_details) > 0
-                ? error_details
-                : "Credentials failed to get metadata."),
-        GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED);
-  } else {
-    GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
+  grpc_error *error = GRPC_ERROR_REF(input_error);
+  if (error == GRPC_ERROR_NONE) {
+    GPR_ASSERT(calld->md_array.size <= MAX_CREDENTIALS_METADATA_COUNT);
     GPR_ASSERT(batch->send_initial_metadata);
     grpc_metadata_batch *mdb =
         batch->payload->send_initial_metadata.send_initial_metadata;
-    for (size_t i = 0; i < num_md; i++) {
-      add_error(&error,
-                grpc_metadata_batch_add_tail(
-                    exec_ctx, mdb, &calld->md_links[i],
-                    grpc_mdelem_from_slices(
-                        exec_ctx, grpc_slice_ref_internal(md_elems[i].key),
-                        grpc_slice_ref_internal(md_elems[i].value))));
+    for (size_t i = 0; i < calld->md_array.size; ++i) {
+      add_error(&error, grpc_metadata_batch_add_tail(
+                            exec_ctx, mdb, &calld->md_links[i],
+                            GRPC_MDELEM_REF(calld->md_array.md[i])));
     }
   }
   if (error == GRPC_ERROR_NONE) {
     grpc_call_next_op(exec_ctx, elem, batch);
   } else {
+    error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
+                               GRPC_STATUS_UNAUTHENTICATED);
     grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error);
   }
 }
@@ -155,6 +187,14 @@
   gpr_free(host);
 }
 
+static void cancel_get_request_metadata(grpc_exec_ctx *exec_ctx, void *arg,
+                                        grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
+  grpc_call_credentials_cancel_get_request_metadata(
+      exec_ctx, calld->creds, &calld->md_array, GRPC_ERROR_REF(error));
+}
+
 static void send_security_metadata(grpc_exec_ctx *exec_ctx,
                                    grpc_call_element *elem,
                                    grpc_transport_stream_op_batch *batch) {
@@ -193,20 +233,33 @@
 
   build_auth_metadata_context(&chand->security_connector->base,
                               chand->auth_context, calld);
+
+  grpc_error *cancel_error = set_cancel_func(elem, cancel_get_request_metadata);
+  if (cancel_error != GRPC_ERROR_NONE) {
+    grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch,
+                                                       cancel_error);
+    return;
+  }
   GPR_ASSERT(calld->pollent != NULL);
-  grpc_call_credentials_get_request_metadata(
-      exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
-      on_credentials_metadata, batch);
+  GRPC_CLOSURE_INIT(&calld->closure, on_credentials_metadata, batch,
+                    grpc_schedule_on_exec_ctx);
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (grpc_call_credentials_get_request_metadata(
+          exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
+          &calld->md_array, &calld->closure, &error)) {
+    // Synchronous return; invoke on_credentials_metadata() directly.
+    on_credentials_metadata(exec_ctx, batch, error);
+    GRPC_ERROR_UNREF(error);
+  }
 }
 
-static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
-                            grpc_security_status status) {
-  grpc_transport_stream_op_batch *batch =
-      (grpc_transport_stream_op_batch *)user_data;
+static void on_host_checked(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error) {
+  grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
   grpc_call_element *elem = batch->handler_private.extra_arg;
   call_data *calld = elem->call_data;
 
-  if (status == GRPC_SECURITY_OK) {
+  if (error == GRPC_ERROR_NONE) {
     send_security_metadata(exec_ctx, elem, batch);
   } else {
     char *error_msg;
@@ -223,6 +276,16 @@
   }
 }
 
+static void cancel_check_call_host(grpc_exec_ctx *exec_ctx, void *arg,
+                                   grpc_error *error) {
+  grpc_call_element *elem = (grpc_call_element *)arg;
+  call_data *calld = (call_data *)elem->call_data;
+  channel_data *chand = (channel_data *)elem->channel_data;
+  grpc_channel_security_connector_cancel_check_call_host(
+      exec_ctx, chand->security_connector, &calld->closure,
+      GRPC_ERROR_REF(error));
+}
+
 static void auth_start_transport_stream_op_batch(
     grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
     grpc_transport_stream_op_batch *batch) {
@@ -232,7 +295,32 @@
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
 
-  if (!batch->cancel_stream) {
+  if (batch->cancel_stream) {
+    while (true) {
+      // Decode the original cancellation state.
+      gpr_atm original_state = gpr_atm_acq_load(&calld->cancellation_state);
+      grpc_error *cancel_error = GRPC_ERROR_NONE;
+      grpc_closure *func = NULL;
+      decode_cancel_state(original_state, &func, &cancel_error);
+      // If we had already set a cancellation error, there's nothing
+      // more to do.
+      if (cancel_error != GRPC_ERROR_NONE) break;
+      // If there's a cancel func, call it.
+      // Note that even if the cancel func has been changed by some
+      // other thread between when we decoded it and now, it will just
+      // be a no-op.
+      cancel_error = GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
+      if (func != NULL) {
+        GRPC_CLOSURE_SCHED(exec_ctx, func, GRPC_ERROR_REF(cancel_error));
+      }
+      // Encode the new error into cancellation state.
+      if (gpr_atm_full_cas(&calld->cancellation_state, original_state,
+                           encode_cancel_state_error(cancel_error))) {
+        break;  // Success.
+      }
+      // The cas failed, so try again.
+    }
+  } else {
     /* double checked lock over security context to ensure it's set once */
     if (gpr_atm_acq_load(&calld->security_context_set) == 0) {
       gpr_mu_lock(&calld->security_context_mu);
@@ -277,12 +365,26 @@
       }
     }
     if (calld->have_host) {
-      char *call_host = grpc_slice_to_c_string(calld->host);
-      batch->handler_private.extra_arg = elem;
-      grpc_channel_security_connector_check_call_host(
-          exec_ctx, chand->security_connector, call_host, chand->auth_context,
-          on_host_checked, batch);
-      gpr_free(call_host);
+      grpc_error *cancel_error = set_cancel_func(elem, cancel_check_call_host);
+      if (cancel_error != GRPC_ERROR_NONE) {
+        grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch,
+                                                           cancel_error);
+      } else {
+        char *call_host = grpc_slice_to_c_string(calld->host);
+        batch->handler_private.extra_arg = elem;
+        grpc_error *error = GRPC_ERROR_NONE;
+        if (grpc_channel_security_connector_check_call_host(
+                exec_ctx, chand->security_connector, call_host,
+                chand->auth_context,
+                GRPC_CLOSURE_INIT(&calld->closure, on_host_checked, batch,
+                                  grpc_schedule_on_exec_ctx),
+                &error)) {
+          // Synchronous return; invoke on_host_checked() directly.
+          on_host_checked(exec_ctx, batch, error);
+          GRPC_ERROR_UNREF(error);
+        }
+        gpr_free(call_host);
+      }
       GPR_TIMER_END("auth_start_transport_stream_op_batch", 0);
       return; /* early exit */
     }
@@ -315,6 +417,7 @@
                               const grpc_call_final_info *final_info,
                               grpc_closure *ignored) {
   call_data *calld = elem->call_data;
+  grpc_credentials_mdelem_array_destroy(exec_ctx, &calld->md_array);
   grpc_call_credentials_unref(exec_ctx, calld->creds);
   if (calld->have_host) {
     grpc_slice_unref_internal(exec_ctx, calld->host);
@@ -324,6 +427,11 @@
   }
   reset_auth_metadata_context(&calld->auth_md_context);
   gpr_mu_destroy(&calld->security_context_mu);
+  gpr_atm cancel_state = gpr_atm_acq_load(&calld->cancellation_state);
+  grpc_error *cancel_error = GRPC_ERROR_NONE;
+  grpc_closure *cancel_func = NULL;
+  decode_cancel_state(cancel_state, &cancel_func, &cancel_error);
+  GRPC_ERROR_UNREF(cancel_error);
 }
 
 /* Constructor for channel_data */
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index f4ed81d..5e41b94 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -60,7 +60,8 @@
   gpr_refcount ref;
 } secure_endpoint;
 
-grpc_tracer_flag grpc_trace_secure_endpoint = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_secure_endpoint =
+    GRPC_TRACER_INITIALIZER(false, "secure_endpoint");
 
 static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
   secure_endpoint *ep = secure_ep;
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 2932710..a7568b9 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -45,7 +45,7 @@
 
 #ifndef NDEBUG
 grpc_tracer_flag grpc_trace_security_connector_refcount =
-    GRPC_TRACER_INITIALIZER(false);
+    GRPC_TRACER_INITIALIZER(false, "security_connector_refcount");
 #endif
 
 /* -- Constants. -- */
@@ -136,15 +136,27 @@
   }
 }
 
-void grpc_channel_security_connector_check_call_host(
+bool grpc_channel_security_connector_check_call_host(
     grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
     const char *host, grpc_auth_context *auth_context,
-    grpc_security_call_host_check_cb cb, void *user_data) {
+    grpc_closure *on_call_host_checked, grpc_error **error) {
   if (sc == NULL || sc->check_call_host == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR);
-  } else {
-    sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data);
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "cannot check call host -- no security connector");
+    return true;
   }
+  return sc->check_call_host(exec_ctx, sc, host, auth_context,
+                             on_call_host_checked, error);
+}
+
+void grpc_channel_security_connector_cancel_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_closure *on_call_host_checked, grpc_error *error) {
+  if (sc == NULL || sc->cancel_check_call_host == NULL) {
+    GRPC_ERROR_UNREF(error);
+    return;
+  }
+  sc->cancel_check_call_host(exec_ctx, sc, on_call_host_checked, error);
 }
 
 #ifndef NDEBUG
@@ -368,13 +380,19 @@
   fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
 }
 
-static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+static bool fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
                                          grpc_channel_security_connector *sc,
                                          const char *host,
                                          grpc_auth_context *auth_context,
-                                         grpc_security_call_host_check_cb cb,
-                                         void *user_data) {
-  cb(exec_ctx, user_data, GRPC_SECURITY_OK);
+                                         grpc_closure *on_call_host_checked,
+                                         grpc_error **error) {
+  return true;
+}
+
+static void fake_channel_cancel_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_closure *on_call_host_checked, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
 }
 
 static void fake_channel_add_handshakers(
@@ -413,6 +431,7 @@
   c->base.request_metadata_creds =
       grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = fake_channel_check_call_host;
+  c->base.cancel_check_call_host = fake_channel_cancel_check_call_host;
   c->base.add_handshakers = fake_channel_add_handshakers;
   c->target = gpr_strdup(target);
   const char *expected_targets = grpc_fake_transport_get_expected_targets(args);
@@ -663,26 +682,35 @@
   if (peer->properties != NULL) gpr_free(peer->properties);
 }
 
-static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+static bool ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
                                         grpc_channel_security_connector *sc,
                                         const char *host,
                                         grpc_auth_context *auth_context,
-                                        grpc_security_call_host_check_cb cb,
-                                        void *user_data) {
+                                        grpc_closure *on_call_host_checked,
+                                        grpc_error **error) {
   grpc_ssl_channel_security_connector *c =
       (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;
-
   /* 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. */
   if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
     status = GRPC_SECURITY_OK;
   }
-  cb(exec_ctx, user_data, status);
+  if (status != GRPC_SECURITY_OK) {
+    *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "call host does not match SSL server name");
+  }
   tsi_shallow_peer_destruct(&peer);
+  return true;
+}
+
+static void ssl_channel_cancel_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_closure *on_call_host_checked, grpc_error *error) {
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_security_connector_vtable ssl_channel_vtable = {
@@ -811,6 +839,7 @@
   c->base.request_metadata_creds =
       grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = ssl_channel_check_call_host;
+  c->base.cancel_check_call_host = ssl_channel_cancel_check_call_host;
   c->base.add_handshakers = ssl_channel_add_handshakers;
   gpr_split_host_port(target_name, &c->target_name, &port);
   gpr_free(port);
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index 1c0fe40..4f9b63a 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -117,27 +117,38 @@
 
 typedef struct grpc_channel_security_connector grpc_channel_security_connector;
 
-typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
-                                                 void *user_data,
-                                                 grpc_security_status status);
-
 struct grpc_channel_security_connector {
   grpc_security_connector base;
   grpc_call_credentials *request_metadata_creds;
-  void (*check_call_host)(grpc_exec_ctx *exec_ctx,
+  bool (*check_call_host)(grpc_exec_ctx *exec_ctx,
                           grpc_channel_security_connector *sc, const char *host,
                           grpc_auth_context *auth_context,
-                          grpc_security_call_host_check_cb cb, void *user_data);
+                          grpc_closure *on_call_host_checked,
+                          grpc_error **error);
+  void (*cancel_check_call_host)(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_security_connector *sc,
+                                 grpc_closure *on_call_host_checked,
+                                 grpc_error *error);
   void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
                           grpc_channel_security_connector *sc,
                           grpc_handshake_manager *handshake_mgr);
 };
 
-/* Checks that the host that will be set for a call is acceptable. */
-void grpc_channel_security_connector_check_call_host(
+/// Checks that the host that will be set for a call is acceptable.
+/// Returns true if completed synchronously, in which case \a error will
+/// be set to indicate the result.  Otherwise, \a on_call_host_checked
+/// will be invoked when complete.
+bool grpc_channel_security_connector_check_call_host(
     grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
     const char *host, grpc_auth_context *auth_context,
-    grpc_security_call_host_check_cb cb, void *user_data);
+    grpc_closure *on_call_host_checked, grpc_error **error);
+
+/// Cancels a pending asychronous call to
+/// grpc_channel_security_connector_check_call_host() with
+/// \a on_call_host_checked as its callback.
+void grpc_channel_security_connector_cancel_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_closure *on_call_host_checked, grpc_error *error);
 
 /* Registers handshakers with \a handshake_mgr. */
 void grpc_channel_security_connector_add_handshakers(
diff --git a/src/core/lib/support/avl.c b/src/core/lib/support/avl.c
index a6178fd..0e28b24 100644
--- a/src/core/lib/support/avl.c
+++ b/src/core/lib/support/avl.c
@@ -39,15 +39,16 @@
   return node;
 }
 
-static void unref_node(const gpr_avl_vtable *vtable, gpr_avl_node *node) {
+static void unref_node(const gpr_avl_vtable *vtable, gpr_avl_node *node,
+                       void *user_data) {
   if (node == NULL) {
     return;
   }
   if (gpr_unref(&node->refs)) {
-    vtable->destroy_key(node->key);
-    vtable->destroy_value(node->value);
-    unref_node(vtable, node->left);
-    unref_node(vtable, node->right);
+    vtable->destroy_key(node->key, user_data);
+    vtable->destroy_value(node->value, user_data);
+    unref_node(vtable, node->left, user_data);
+    unref_node(vtable, node->right, user_data);
     gpr_free(node);
   }
 }
@@ -87,30 +88,30 @@
 }
 
 static gpr_avl_node *get(const gpr_avl_vtable *vtable, gpr_avl_node *node,
-                         void *key) {
+                         void *key, void *user_data) {
   long cmp;
 
   if (node == NULL) {
     return NULL;
   }
 
-  cmp = vtable->compare_keys(node->key, key);
+  cmp = vtable->compare_keys(node->key, key, user_data);
   if (cmp == 0) {
     return node;
   } else if (cmp > 0) {
-    return get(vtable, node->left, key);
+    return get(vtable, node->left, key, user_data);
   } else {
-    return get(vtable, node->right, key);
+    return get(vtable, node->right, key, user_data);
   }
 }
 
-void *gpr_avl_get(gpr_avl avl, void *key) {
-  gpr_avl_node *node = get(avl.vtable, avl.root, key);
+void *gpr_avl_get(gpr_avl avl, void *key, void *user_data) {
+  gpr_avl_node *node = get(avl.vtable, avl.root, key, user_data);
   return node ? node->value : NULL;
 }
 
-int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value) {
-  gpr_avl_node *node = get(avl.vtable, avl.root, key);
+int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value, void *user_data) {
+  gpr_avl_node *node = get(avl.vtable, avl.root, key, user_data);
   if (node != NULL) {
     *value = node->value;
     return 1;
@@ -120,70 +121,75 @@
 
 static gpr_avl_node *rotate_left(const gpr_avl_vtable *vtable, void *key,
                                  void *value, gpr_avl_node *left,
-                                 gpr_avl_node *right) {
-  gpr_avl_node *n =
-      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
-               new_node(key, value, left, ref_node(right->left)),
-               ref_node(right->right));
-  unref_node(vtable, right);
+                                 gpr_avl_node *right, void *user_data) {
+  gpr_avl_node *n = new_node(vtable->copy_key(right->key, user_data),
+                             vtable->copy_value(right->value, user_data),
+                             new_node(key, value, left, ref_node(right->left)),
+                             ref_node(right->right));
+  unref_node(vtable, right, user_data);
   return n;
 }
 
 static gpr_avl_node *rotate_right(const gpr_avl_vtable *vtable, void *key,
                                   void *value, gpr_avl_node *left,
-                                  gpr_avl_node *right) {
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(left->key), vtable->copy_value(left->value),
-      ref_node(left->left), new_node(key, value, ref_node(left->right), right));
-  unref_node(vtable, left);
+                                  gpr_avl_node *right, void *user_data) {
+  gpr_avl_node *n =
+      new_node(vtable->copy_key(left->key, user_data),
+               vtable->copy_value(left->value, user_data), ref_node(left->left),
+               new_node(key, value, ref_node(left->right), right));
+  unref_node(vtable, left, user_data);
   return n;
 }
 
 static gpr_avl_node *rotate_left_right(const gpr_avl_vtable *vtable, void *key,
                                        void *value, gpr_avl_node *left,
-                                       gpr_avl_node *right) {
+                                       gpr_avl_node *right, void *user_data) {
   /* rotate_right(..., rotate_left(left), right) */
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(left->right->key),
-      vtable->copy_value(left->right->value),
-      new_node(vtable->copy_key(left->key), vtable->copy_value(left->value),
-               ref_node(left->left), ref_node(left->right->left)),
-      new_node(key, value, ref_node(left->right->right), right));
-  unref_node(vtable, left);
+  gpr_avl_node *n =
+      new_node(vtable->copy_key(left->right->key, user_data),
+               vtable->copy_value(left->right->value, user_data),
+               new_node(vtable->copy_key(left->key, user_data),
+                        vtable->copy_value(left->value, user_data),
+                        ref_node(left->left), ref_node(left->right->left)),
+               new_node(key, value, ref_node(left->right->right), right));
+  unref_node(vtable, left, user_data);
   return n;
 }
 
 static gpr_avl_node *rotate_right_left(const gpr_avl_vtable *vtable, void *key,
                                        void *value, gpr_avl_node *left,
-                                       gpr_avl_node *right) {
+                                       gpr_avl_node *right, void *user_data) {
   /* rotate_left(..., left, rotate_right(right)) */
-  gpr_avl_node *n = new_node(
-      vtable->copy_key(right->left->key),
-      vtable->copy_value(right->left->value),
-      new_node(key, value, left, ref_node(right->left->left)),
-      new_node(vtable->copy_key(right->key), vtable->copy_value(right->value),
-               ref_node(right->left->right), ref_node(right->right)));
-  unref_node(vtable, right);
+  gpr_avl_node *n =
+      new_node(vtable->copy_key(right->left->key, user_data),
+               vtable->copy_value(right->left->value, user_data),
+               new_node(key, value, left, ref_node(right->left->left)),
+               new_node(vtable->copy_key(right->key, user_data),
+                        vtable->copy_value(right->value, user_data),
+                        ref_node(right->left->right), ref_node(right->right)));
+  unref_node(vtable, right, user_data);
   return n;
 }
 
 static gpr_avl_node *rebalance(const gpr_avl_vtable *vtable, void *key,
                                void *value, gpr_avl_node *left,
-                               gpr_avl_node *right) {
+                               gpr_avl_node *right, void *user_data) {
   switch (node_height(left) - node_height(right)) {
     case 2:
       if (node_height(left->left) - node_height(left->right) == -1) {
         return assert_invariants(
-            rotate_left_right(vtable, key, value, left, right));
+            rotate_left_right(vtable, key, value, left, right, user_data));
       } else {
-        return assert_invariants(rotate_right(vtable, key, value, left, right));
+        return assert_invariants(
+            rotate_right(vtable, key, value, left, right, user_data));
       }
     case -2:
       if (node_height(right->left) - node_height(right->right) == 1) {
         return assert_invariants(
-            rotate_right_left(vtable, key, value, left, right));
+            rotate_right_left(vtable, key, value, left, right, user_data));
       } else {
-        return assert_invariants(rotate_left(vtable, key, value, left, right));
+        return assert_invariants(
+            rotate_left(vtable, key, value, left, right, user_data));
       }
     default:
       return assert_invariants(new_node(key, value, left, right));
@@ -191,30 +197,32 @@
 }
 
 static gpr_avl_node *add_key(const gpr_avl_vtable *vtable, gpr_avl_node *node,
-                             void *key, void *value) {
+                             void *key, void *value, void *user_data) {
   long cmp;
   if (node == NULL) {
     return new_node(key, value, NULL, NULL);
   }
-  cmp = vtable->compare_keys(node->key, key);
+  cmp = vtable->compare_keys(node->key, key, user_data);
   if (cmp == 0) {
     return new_node(key, value, ref_node(node->left), ref_node(node->right));
   } else if (cmp > 0) {
-    return rebalance(
-        vtable, vtable->copy_key(node->key), vtable->copy_value(node->value),
-        add_key(vtable, node->left, key, value), ref_node(node->right));
+    return rebalance(vtable, vtable->copy_key(node->key, user_data),
+                     vtable->copy_value(node->value, user_data),
+                     add_key(vtable, node->left, key, value, user_data),
+                     ref_node(node->right), user_data);
   } else {
-    return rebalance(vtable, vtable->copy_key(node->key),
-                     vtable->copy_value(node->value), ref_node(node->left),
-                     add_key(vtable, node->right, key, value));
+    return rebalance(
+        vtable, vtable->copy_key(node->key, user_data),
+        vtable->copy_value(node->value, user_data), ref_node(node->left),
+        add_key(vtable, node->right, key, value, user_data), user_data);
   }
 }
 
-gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value) {
+gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value, void *user_data) {
   gpr_avl_node *old_root = avl.root;
-  avl.root = add_key(avl.vtable, avl.root, key, value);
+  avl.root = add_key(avl.vtable, avl.root, key, value, user_data);
   assert_invariants(avl.root);
-  unref_node(avl.vtable, old_root);
+  unref_node(avl.vtable, old_root, user_data);
   return avl;
 }
 
@@ -233,12 +241,13 @@
 }
 
 static gpr_avl_node *remove_key(const gpr_avl_vtable *vtable,
-                                gpr_avl_node *node, void *key) {
+                                gpr_avl_node *node, void *key,
+                                void *user_data) {
   long cmp;
   if (node == NULL) {
     return NULL;
   }
-  cmp = vtable->compare_keys(node->key, key);
+  cmp = vtable->compare_keys(node->key, key, user_data);
   if (cmp == 0) {
     if (node->left == NULL) {
       return ref_node(node->right);
@@ -246,39 +255,45 @@
       return ref_node(node->left);
     } else if (node->left->height < node->right->height) {
       gpr_avl_node *h = in_order_head(node->right);
-      return rebalance(vtable, vtable->copy_key(h->key),
-                       vtable->copy_value(h->value), ref_node(node->left),
-                       remove_key(vtable, node->right, h->key));
+      return rebalance(
+          vtable, vtable->copy_key(h->key, user_data),
+          vtable->copy_value(h->value, user_data), ref_node(node->left),
+          remove_key(vtable, node->right, h->key, user_data), user_data);
     } else {
       gpr_avl_node *h = in_order_tail(node->left);
-      return rebalance(
-          vtable, vtable->copy_key(h->key), vtable->copy_value(h->value),
-          remove_key(vtable, node->left, h->key), ref_node(node->right));
+      return rebalance(vtable, vtable->copy_key(h->key, user_data),
+                       vtable->copy_value(h->value, user_data),
+                       remove_key(vtable, node->left, h->key, user_data),
+                       ref_node(node->right), user_data);
     }
   } else if (cmp > 0) {
-    return rebalance(
-        vtable, vtable->copy_key(node->key), vtable->copy_value(node->value),
-        remove_key(vtable, node->left, key), ref_node(node->right));
+    return rebalance(vtable, vtable->copy_key(node->key, user_data),
+                     vtable->copy_value(node->value, user_data),
+                     remove_key(vtable, node->left, key, user_data),
+                     ref_node(node->right), user_data);
   } else {
-    return rebalance(vtable, vtable->copy_key(node->key),
-                     vtable->copy_value(node->value), ref_node(node->left),
-                     remove_key(vtable, node->right, key));
+    return rebalance(
+        vtable, vtable->copy_key(node->key, user_data),
+        vtable->copy_value(node->value, user_data), ref_node(node->left),
+        remove_key(vtable, node->right, key, user_data), user_data);
   }
 }
 
-gpr_avl gpr_avl_remove(gpr_avl avl, void *key) {
+gpr_avl gpr_avl_remove(gpr_avl avl, void *key, void *user_data) {
   gpr_avl_node *old_root = avl.root;
-  avl.root = remove_key(avl.vtable, avl.root, key);
+  avl.root = remove_key(avl.vtable, avl.root, key, user_data);
   assert_invariants(avl.root);
-  unref_node(avl.vtable, old_root);
+  unref_node(avl.vtable, old_root, user_data);
   return avl;
 }
 
-gpr_avl gpr_avl_ref(gpr_avl avl) {
+gpr_avl gpr_avl_ref(gpr_avl avl, void *user_data) {
   ref_node(avl.root);
   return avl;
 }
 
-void gpr_avl_unref(gpr_avl avl) { unref_node(avl.vtable, avl.root); }
+void gpr_avl_unref(gpr_avl avl, void *user_data) {
+  unref_node(avl.vtable, avl.root, user_data);
+}
 
 int gpr_avl_is_empty(gpr_avl avl) { return avl.root == NULL; }
diff --git a/src/core/lib/support/env.h b/src/core/lib/support/env.h
index 18bc08a..e2c012a 100644
--- a/src/core/lib/support/env.h
+++ b/src/core/lib/support/env.h
@@ -36,6 +36,12 @@
 /* Sets the the environment with the specified name to the specified value. */
 void gpr_setenv(const char *name, const char *value);
 
+/* This is a version of gpr_getenv that does not produce any output if it has to
+   use an insecure version of the function. It is ONLY to be used to solve the
+   problem in which we need to check an env variable to configure the verbosity
+   level of logging. So DO NOT USE THIS. */
+const char *gpr_getenv_silent(const char *name, char **dst);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/core/lib/support/env_linux.c b/src/core/lib/support/env_linux.c
index 0c79a2c..4c45a97 100644
--- a/src/core/lib/support/env_linux.c
+++ b/src/core/lib/support/env_linux.c
@@ -38,7 +38,9 @@
 
 #include "src/core/lib/support/string.h"
 
-char *gpr_getenv(const char *name) {
+const char *gpr_getenv_silent(const char *name, char **dst) {
+  const char *insecure_func_used = NULL;
+  char *result = NULL;
 #if defined(GPR_BACKWARDS_COMPATIBILITY_MODE)
   typedef char *(*getenv_type)(const char *);
   static getenv_type getenv_func = NULL;
@@ -48,22 +50,28 @@
   for (size_t i = 0; getenv_func == NULL && i < GPR_ARRAY_SIZE(names); i++) {
     getenv_func = (getenv_type)dlsym(RTLD_DEFAULT, names[i]);
     if (getenv_func != NULL && strstr(names[i], "secure") == NULL) {
-      gpr_log(GPR_DEBUG,
-              "Warning: insecure environment read function '%s' used",
-              names[i]);
+      insecure_func_used = names[i];
     }
   }
-  char *result = getenv_func(name);
-  return result == NULL ? result : gpr_strdup(result);
+  result = getenv_func(name);
 #elif __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17)
-  char *result = secure_getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
+  result = secure_getenv(name);
 #else
-  gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
-          "getenv");
-  char *result = getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
+  result = getenv(name);
+  insecure_func_used = "getenv";
 #endif
+  *dst = result == NULL ? result : gpr_strdup(result);
+  return insecure_func_used;
+}
+
+char *gpr_getenv(const char *name) {
+  char *result = NULL;
+  const char *insecure_func_used = gpr_getenv_silent(name, &result);
+  if (insecure_func_used != NULL) {
+    gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
+            insecure_func_used);
+  }
+  return result;
 }
 
 void gpr_setenv(const char *name, const char *value) {
diff --git a/src/core/lib/support/env_posix.c b/src/core/lib/support/env_posix.c
index bdbc4da..b88822c 100644
--- a/src/core/lib/support/env_posix.c
+++ b/src/core/lib/support/env_posix.c
@@ -29,6 +29,11 @@
 #include <grpc/support/string_util.h>
 #include "src/core/lib/support/string.h"
 
+const char *gpr_getenv_silent(const char *name, char **dst) {
+  *dst = gpr_getenv(name);
+  return NULL;
+}
+
 char *gpr_getenv(const char *name) {
   char *result = getenv(name);
   return result == NULL ? result : gpr_strdup(result);
diff --git a/src/core/lib/support/env_windows.c b/src/core/lib/support/env_windows.c
index c1d557e..652eeb6 100644
--- a/src/core/lib/support/env_windows.c
+++ b/src/core/lib/support/env_windows.c
@@ -30,6 +30,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+const char *gpr_getenv_silent(const char *name, char **dst) {
+  *dst = gpr_getenv(name);
+  return NULL;
+}
+
 char *gpr_getenv(const char *name) {
   char *result = NULL;
   DWORD size;
diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c
index bcc336b..fadb4d9 100644
--- a/src/core/lib/support/log.c
+++ b/src/core/lib/support/log.c
@@ -64,7 +64,8 @@
 }
 
 void gpr_log_verbosity_init() {
-  char *verbosity = gpr_getenv("GRPC_VERBOSITY");
+  char *verbosity = NULL;
+  const char *insecure_getenv = gpr_getenv_silent("GRPC_VERBOSITY", &verbosity);
 
   gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR;
   if (verbosity != NULL) {
@@ -81,6 +82,11 @@
       GPR_LOG_VERBOSITY_UNSET) {
     gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print);
   }
+
+  if (insecure_getenv != NULL) {
+    gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
+            insecure_getenv);
+  }
 }
 
 void gpr_set_log_function(gpr_log_func f) {
diff --git a/src/core/lib/surface/alarm.c b/src/core/lib/surface/alarm.c
index ef8405c..5593496 100644
--- a/src/core/lib/surface/alarm.c
+++ b/src/core/lib/surface/alarm.c
@@ -18,6 +18,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/surface/completion_queue.h"
 
@@ -49,7 +50,7 @@
   alarm->cq = cq;
   alarm->tag = tag;
 
-  grpc_cq_begin_op(cq, tag);
+  GPR_ASSERT(grpc_cq_begin_op(cq, tag));
   GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm,
                     grpc_schedule_on_exec_ctx);
   grpc_timer_init(&exec_ctx, &alarm->alarm,
diff --git a/src/core/lib/surface/api_trace.c b/src/core/lib/surface/api_trace.c
index f88ffd5..5697330 100644
--- a/src/core/lib/surface/api_trace.c
+++ b/src/core/lib/surface/api_trace.c
@@ -19,4 +19,4 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/debug/trace.h"
 
-grpc_tracer_flag grpc_api_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_api_trace = GRPC_TRACER_INITIALIZER(false, "api");
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index aac443e..00ec9c7 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -229,8 +229,10 @@
   void *saved_receiving_stream_ready_bctlp;
 };
 
-grpc_tracer_flag grpc_call_error_trace = GRPC_TRACER_INITIALIZER(false);
-grpc_tracer_flag grpc_compression_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_call_error_trace =
+    GRPC_TRACER_INITIALIZER(false, "call_error");
+grpc_tracer_flag grpc_compression_trace =
+    GRPC_TRACER_INITIALIZER(false, "compression");
 
 #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
 #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
@@ -642,6 +644,8 @@
 
 static grpc_error *error_from_status(grpc_status_code status,
                                      const char *description) {
+  // copying 'description' is needed to ensure the grpc_call_cancel_with_status
+  // guarantee that can be short-lived.
   return grpc_error_set_int(
       grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description),
                          GRPC_ERROR_STR_GRPC_MESSAGE,
@@ -821,7 +825,7 @@
   return encodings_accepted_by_peer;
 }
 
-static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
+static grpc_linked_mdelem *linked_from_md(const grpc_metadata *md) {
   return (grpc_linked_mdelem *)&md->internal_data;
 }
 
@@ -845,7 +849,7 @@
   for (i = 0; i < total_count; i++) {
     const grpc_metadata *md =
         get_md_elem(metadata, additional_metadata, i, count);
-    grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+    grpc_linked_mdelem *l = linked_from_md(md);
     GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
     if (!GRPC_LOG_IF_ERROR("validate_metadata",
                            grpc_validate_header_key_is_legal(md->key))) {
@@ -862,7 +866,7 @@
     for (int j = 0; j < i; j++) {
       const grpc_metadata *md =
           get_md_elem(metadata, additional_metadata, j, count);
-      grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+      grpc_linked_mdelem *l = linked_from_md(md);
       GRPC_MDELEM_UNREF(exec_ctx, l->md);
     }
     return 0;
@@ -880,9 +884,12 @@
   }
   for (i = 0; i < total_count; i++) {
     grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
-    GRPC_LOG_IF_ERROR(
-        "prepare_application_metadata",
-        grpc_metadata_batch_link_tail(exec_ctx, batch, linked_from_md(md)));
+    grpc_linked_mdelem *l = linked_from_md(md);
+    grpc_error *error = grpc_metadata_batch_link_tail(exec_ctx, batch, l);
+    if (error != GRPC_ERROR_NONE) {
+      GRPC_MDELEM_UNREF(exec_ctx, l->md);
+    }
+    GRPC_LOG_IF_ERROR("prepare_application_metadata", error);
   }
   call->send_extra_metadata_count = 0;
 
@@ -1420,7 +1427,7 @@
 
   if (nops == 0) {
     if (!is_notify_tag_closure) {
-      grpc_cq_begin_op(call->cq, notify_tag);
+      GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
       grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
                      free_no_op_completion, NULL,
                      gpr_malloc(sizeof(grpc_cq_completion)));
@@ -1721,7 +1728,7 @@
 
   GRPC_CALL_INTERNAL_REF(call, "completion");
   if (!is_notify_tag_closure) {
-    grpc_cq_begin_op(call->cq, notify_tag);
+    GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
   }
   gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
 
@@ -1842,6 +1849,8 @@
       return "GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH";
     case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS:
       return "GRPC_CALL_ERROR_TOO_MANY_OPERATIONS";
+    case GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN:
+      return "GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN";
     case GRPC_CALL_OK:
       return "GRPC_CALL_OK";
   }
diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c
index 80eb80a..e85b308 100644
--- a/src/core/lib/surface/channel_ping.c
+++ b/src/core/lib/surface/channel_ping.c
@@ -59,7 +59,7 @@
   GRPC_CLOSURE_INIT(&pr->closure, ping_done, pr, grpc_schedule_on_exec_ctx);
   op->send_ping = &pr->closure;
   op->bind_pollset = grpc_cq_pollset(cq);
-  grpc_cq_begin_op(cq, tag);
+  GPR_ASSERT(grpc_cq_begin_op(cq, tag));
   top_elem->filter->start_transport_op(&exec_ctx, top_elem, op);
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index 14e55ed..3d82a32 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -35,10 +35,13 @@
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/event_string.h"
 
-grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_operation_failures =
+    GRPC_TRACER_INITIALIZER(false, "op_failure");
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_pending_tags = GRPC_TRACER_INITIALIZER(false);
-grpc_tracer_flag grpc_trace_cq_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_pending_tags =
+    GRPC_TRACER_INITIALIZER(false, "pending_tags");
+grpc_tracer_flag grpc_trace_cq_refcount =
+    GRPC_TRACER_INITIALIZER(false, "cq_refcount");
 #endif
 
 typedef struct {
@@ -193,7 +196,7 @@
   void (*init)(void *data);
   void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cq);
   void (*destroy)(void *data);
-  void (*begin_op)(grpc_completion_queue *cq, void *tag);
+  bool (*begin_op)(grpc_completion_queue *cq, void *tag);
   void (*end_op)(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cq, void *tag,
                  grpc_error *error,
                  void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
@@ -285,8 +288,8 @@
 static void cq_shutdown_pluck(grpc_exec_ctx *exec_ctx,
                               grpc_completion_queue *cq);
 
-static void cq_begin_op_for_next(grpc_completion_queue *cq, void *tag);
-static void cq_begin_op_for_pluck(grpc_completion_queue *cq, void *tag);
+static bool cq_begin_op_for_next(grpc_completion_queue *cq, void *tag);
+static bool cq_begin_op_for_pluck(grpc_completion_queue *cq, void *tag);
 
 static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
                                grpc_completion_queue *cq, void *tag,
@@ -343,8 +346,10 @@
 #define POLLSET_FROM_CQ(cq) \
   ((grpc_pollset *)(cq->vtable->data_size + (char *)DATA_FROM_CQ(cq)))
 
-grpc_tracer_flag grpc_cq_pluck_trace = GRPC_TRACER_INITIALIZER(true);
-grpc_tracer_flag grpc_cq_event_timeout_trace = GRPC_TRACER_INITIALIZER(true);
+grpc_tracer_flag grpc_cq_pluck_trace =
+    GRPC_TRACER_INITIALIZER(true, "queue_pluck");
+grpc_tracer_flag grpc_cq_event_timeout_trace =
+    GRPC_TRACER_INITIALIZER(true, "queue_timeout");
 
 #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)    \
   if (GRPC_TRACER_ON(grpc_api_trace) &&                 \
@@ -517,33 +522,6 @@
   }
 }
 
-static void cq_begin_op_for_next(grpc_completion_queue *cq, void *tag) {
-  cq_next_data *cqd = DATA_FROM_CQ(cq);
-  GPR_ASSERT(!cqd->shutdown_called);
-  gpr_atm_no_barrier_fetch_add(&cqd->pending_events, 1);
-}
-
-static void cq_begin_op_for_pluck(grpc_completion_queue *cq, void *tag) {
-  cq_pluck_data *cqd = DATA_FROM_CQ(cq);
-  GPR_ASSERT(!cqd->shutdown_called);
-  gpr_ref(&cqd->pending_events);
-}
-
-void grpc_cq_begin_op(grpc_completion_queue *cq, void *tag) {
-#ifndef NDEBUG
-  gpr_mu_lock(cq->mu);
-  if (cq->outstanding_tag_count == cq->outstanding_tag_capacity) {
-    cq->outstanding_tag_capacity = GPR_MAX(4, 2 * cq->outstanding_tag_capacity);
-    cq->outstanding_tags =
-        gpr_realloc(cq->outstanding_tags, sizeof(*cq->outstanding_tags) *
-                                              cq->outstanding_tag_capacity);
-  }
-  cq->outstanding_tags[cq->outstanding_tag_count++] = tag;
-  gpr_mu_unlock(cq->mu);
-#endif
-  cq->vtable->begin_op(cq, tag);
-}
-
 #ifndef NDEBUG
 static void cq_check_tag(grpc_completion_queue *cq, void *tag, bool lock_cq) {
   int found = 0;
@@ -571,6 +549,41 @@
 static void cq_check_tag(grpc_completion_queue *cq, void *tag, bool lock_cq) {}
 #endif
 
+static bool cq_begin_op_for_next(grpc_completion_queue *cq, void *tag) {
+  cq_next_data *cqd = DATA_FROM_CQ(cq);
+  while (true) {
+    gpr_atm count = gpr_atm_no_barrier_load(&cqd->pending_events);
+    if (count == 0) {
+      return false;
+    } else if (gpr_atm_no_barrier_cas(&cqd->pending_events, count, count + 1)) {
+      break;
+    }
+  }
+  return true;
+}
+
+static bool cq_begin_op_for_pluck(grpc_completion_queue *cq, void *tag) {
+  cq_pluck_data *cqd = DATA_FROM_CQ(cq);
+  GPR_ASSERT(!cqd->shutdown_called);
+  gpr_ref(&cqd->pending_events);
+  return true;
+}
+
+bool grpc_cq_begin_op(grpc_completion_queue *cq, void *tag) {
+#ifndef NDEBUG
+  gpr_mu_lock(cq->mu);
+  if (cq->outstanding_tag_count == cq->outstanding_tag_capacity) {
+    cq->outstanding_tag_capacity = GPR_MAX(4, 2 * cq->outstanding_tag_capacity);
+    cq->outstanding_tags =
+        gpr_realloc(cq->outstanding_tags, sizeof(*cq->outstanding_tags) *
+                                              cq->outstanding_tag_capacity);
+  }
+  cq->outstanding_tags[cq->outstanding_tag_count++] = tag;
+  gpr_mu_unlock(cq->mu);
+#endif
+  return cq->vtable->begin_op(cq, tag);
+}
+
 /* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a
  * completion
  * type of GRPC_CQ_NEXT) */
@@ -850,8 +863,7 @@
          inconsistent state. If it is the latter, we shold do a 0-timeout poll
          so that the thread comes back quickly from poll to make a second
          attempt at popping. Not doing this can potentially deadlock this
-         thread
-         forever (if the deadline is infinity) */
+         thread forever (if the deadline is infinity) */
       if (cq_event_queue_num_items(&cqd->queue) > 0) {
         iteration_deadline = gpr_time_0(GPR_CLOCK_MONOTONIC);
       }
@@ -864,10 +876,8 @@
       if (cq_event_queue_num_items(&cqd->queue) > 0) {
         /* Go to the beginning of the loop. No point doing a poll because
            (cq->shutdown == true) is only possible when there is no pending
-           work
-           (i.e cq->pending_events == 0) and any outstanding
-           grpc_cq_completion
-           events are already queued on this cq */
+           work (i.e cq->pending_events == 0) and any outstanding completion
+           events should have already been queued on this cq */
         continue;
       }
 
@@ -904,11 +914,6 @@
     is_finished_arg.first_loop = false;
   }
 
-  GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, &ret);
-  GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cq, "next");
-  grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(is_finished_arg.stolen_completion == NULL);
-
   if (cq_event_queue_num_items(&cqd->queue) > 0 &&
       gpr_atm_no_barrier_load(&cqd->pending_events) > 0) {
     gpr_mu_lock(cq->mu);
@@ -916,6 +921,11 @@
     gpr_mu_unlock(cq->mu);
   }
 
+  GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, &ret);
+  GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cq, "next");
+  grpc_exec_ctx_finish(&exec_ctx);
+  GPR_ASSERT(is_finished_arg.stolen_completion == NULL);
+
   GPR_TIMER_END("grpc_completion_queue_next", 0);
 
   return ret;
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index af44482..69d144b 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -72,8 +72,9 @@
 
 /* Flag that an operation is beginning: the completion channel will not finish
    shutdown until a corrensponding grpc_cq_end_* call is made.
-   \a tag is currently used only in debug builds. */
-void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag);
+   \a tag is currently used only in debug builds. Return true on success, and
+   false if completion_queue has been shutdown. */
+bool grpc_cq_begin_op(grpc_completion_queue *cc, void *tag);
 
 /* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to
    grpc_cq_begin_op */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index 14a86bf..db111e5 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -120,29 +120,27 @@
     grpc_slice_intern_init();
     grpc_mdctx_global_init();
     grpc_channel_init_init();
-    grpc_register_tracer("api", &grpc_api_trace);
-    grpc_register_tracer("channel", &grpc_trace_channel);
-    grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace);
-    grpc_register_tracer("channel_stack_builder",
-                         &grpc_trace_channel_stack_builder);
-    grpc_register_tracer("http1", &grpc_http1_trace);
-    grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace);  // default on
-    grpc_register_tracer("combiner", &grpc_combiner_trace);
-    grpc_register_tracer("server_channel", &grpc_server_channel_trace);
-    grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace);
-    grpc_register_tracer("queue_timeout",
-                         &grpc_cq_event_timeout_trace);  // default on
-    grpc_register_tracer("op_failure", &grpc_trace_operation_failures);
-    grpc_register_tracer("resource_quota", &grpc_resource_quota_trace);
-    grpc_register_tracer("call_error", &grpc_call_error_trace);
+    grpc_register_tracer(&grpc_api_trace);
+    grpc_register_tracer(&grpc_trace_channel);
+    grpc_register_tracer(&grpc_connectivity_state_trace);
+    grpc_register_tracer(&grpc_trace_channel_stack_builder);
+    grpc_register_tracer(&grpc_http1_trace);
+    grpc_register_tracer(&grpc_cq_pluck_trace);  // default on
+    grpc_register_tracer(&grpc_combiner_trace);
+    grpc_register_tracer(&grpc_server_channel_trace);
+    grpc_register_tracer(&grpc_bdp_estimator_trace);
+    grpc_register_tracer(&grpc_cq_event_timeout_trace);  // default on
+    grpc_register_tracer(&grpc_trace_operation_failures);
+    grpc_register_tracer(&grpc_resource_quota_trace);
+    grpc_register_tracer(&grpc_call_error_trace);
 #ifndef NDEBUG
-    grpc_register_tracer("pending_tags", &grpc_trace_pending_tags);
-    grpc_register_tracer("queue_refcount", &grpc_trace_cq_refcount);
-    grpc_register_tracer("closure", &grpc_trace_closure);
-    grpc_register_tracer("error_refcount", &grpc_trace_error_refcount);
-    grpc_register_tracer("stream_refcount", &grpc_trace_stream_refcount);
-    grpc_register_tracer("fd_refcount", &grpc_trace_fd_refcount);
-    grpc_register_tracer("metadata", &grpc_trace_metadata);
+    grpc_register_tracer(&grpc_trace_pending_tags);
+    grpc_register_tracer(&grpc_trace_cq_refcount);
+    grpc_register_tracer(&grpc_trace_closure);
+    grpc_register_tracer(&grpc_trace_error_refcount);
+    grpc_register_tracer(&grpc_trace_stream_refcount);
+    grpc_register_tracer(&grpc_trace_fd_refcount);
+    grpc_register_tracer(&grpc_trace_metadata);
 #endif
     grpc_security_pre_init();
     grpc_iomgr_init(&exec_ctx);
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
index 7dbea58..2366c24 100644
--- a/src/core/lib/surface/init_secure.c
+++ b/src/core/lib/surface/init_secure.c
@@ -37,13 +37,11 @@
 #endif
 
 void grpc_security_pre_init(void) {
-  grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint);
-  grpc_register_tracer("transport_security", &tsi_tracing_enabled);
+  grpc_register_tracer(&grpc_trace_secure_endpoint);
+  grpc_register_tracer(&tsi_tracing_enabled);
 #ifndef NDEBUG
-  grpc_register_tracer("auth_context_refcount",
-                       &grpc_trace_auth_context_refcount);
-  grpc_register_tracer("security_connector_refcount",
-                       &grpc_trace_security_connector_refcount);
+  grpc_register_tracer(&grpc_trace_auth_context_refcount);
+  grpc_register_tracer(&grpc_trace_security_connector_refcount);
 #endif
 }
 
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index de0a91e..66dcc29 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -58,7 +58,8 @@
 
 typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
 
-grpc_tracer_flag grpc_server_channel_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_server_channel_trace =
+    GRPC_TRACER_INITIALIZER(false, "server_channel");
 
 typedef struct requested_call {
   requested_call_type type;
@@ -1258,7 +1259,7 @@
   }
 
   /* stay locked, and gather up some stuff to do */
-  grpc_cq_begin_op(cq, tag);
+  GPR_ASSERT(grpc_cq_begin_op(cq, tag));
   if (server->shutdown_published) {
     grpc_cq_end_op(&exec_ctx, cq, tag, GRPC_ERROR_NONE, done_published_shutdown,
                    NULL, gpr_malloc(sizeof(grpc_cq_completion)));
@@ -1445,7 +1446,11 @@
     error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
     goto done;
   }
-  grpc_cq_begin_op(cq_for_notification, tag);
+  if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
+    gpr_free(rc);
+    error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
+    goto done;
+  }
   details->reserved = NULL;
   rc->cq_idx = cq_idx;
   rc->type = BATCH_CALL;
@@ -1495,7 +1500,11 @@
     error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
     goto done;
   }
-  grpc_cq_begin_op(cq_for_notification, tag);
+  if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
+    gpr_free(rc);
+    error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
+    goto done;
+  }
   rc->cq_idx = cq_idx;
   rc->type = REGISTERED_CALL;
   rc->server = server;
diff --git a/src/core/lib/transport/bdp_estimator.c b/src/core/lib/transport/bdp_estimator.c
index d33e3a4..311ae63 100644
--- a/src/core/lib/transport/bdp_estimator.c
+++ b/src/core/lib/transport/bdp_estimator.c
@@ -23,7 +23,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-grpc_tracer_flag grpc_bdp_estimator_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_bdp_estimator_trace =
+    GRPC_TRACER_INITIALIZER(false, "bdp_estimator");
 
 void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) {
   estimator->estimate = 65536;
diff --git a/src/core/lib/transport/byte_stream.c b/src/core/lib/transport/byte_stream.c
index 3355814..fb03a10 100644
--- a/src/core/lib/transport/byte_stream.c
+++ b/src/core/lib/transport/byte_stream.c
@@ -19,29 +19,37 @@
 #include "src/core/lib/transport/byte_stream.h"
 
 #include <stdlib.h>
+#include <string.h>
 
 #include <grpc/support/log.h>
 
 #include "src/core/lib/slice/slice_internal.h"
 
-int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                          grpc_byte_stream *byte_stream, size_t max_size_hint,
-                          grpc_closure *on_complete) {
-  return byte_stream->next(exec_ctx, byte_stream, max_size_hint, on_complete);
+bool grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                           grpc_byte_stream *byte_stream, size_t max_size_hint,
+                           grpc_closure *on_complete) {
+  return byte_stream->vtable->next(exec_ctx, byte_stream, max_size_hint,
+                                   on_complete);
 }
 
 grpc_error *grpc_byte_stream_pull(grpc_exec_ctx *exec_ctx,
                                   grpc_byte_stream *byte_stream,
                                   grpc_slice *slice) {
-  return byte_stream->pull(exec_ctx, byte_stream, slice);
+  return byte_stream->vtable->pull(exec_ctx, byte_stream, slice);
+}
+
+void grpc_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                               grpc_byte_stream *byte_stream,
+                               grpc_error *error) {
+  byte_stream->vtable->shutdown(exec_ctx, byte_stream, error);
 }
 
 void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
                               grpc_byte_stream *byte_stream) {
-  byte_stream->destroy(exec_ctx, byte_stream);
+  byte_stream->vtable->destroy(exec_ctx, byte_stream);
 }
 
-/* slice_buffer_stream */
+// grpc_slice_buffer_stream
 
 static bool slice_buffer_stream_next(grpc_exec_ctx *exec_ctx,
                                      grpc_byte_stream *byte_stream,
@@ -56,6 +64,9 @@
                                             grpc_byte_stream *byte_stream,
                                             grpc_slice *slice) {
   grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
+  if (stream->shutdown_error != GRPC_ERROR_NONE) {
+    return GRPC_ERROR_REF(stream->shutdown_error);
+  }
   GPR_ASSERT(stream->cursor < stream->backing_buffer->count);
   *slice =
       grpc_slice_ref_internal(stream->backing_buffer->slices[stream->cursor]);
@@ -63,8 +74,23 @@
   return GRPC_ERROR_NONE;
 }
 
+static void slice_buffer_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                                         grpc_byte_stream *byte_stream,
+                                         grpc_error *error) {
+  grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+  stream->shutdown_error = error;
+}
+
 static void slice_buffer_stream_destroy(grpc_exec_ctx *exec_ctx,
-                                        grpc_byte_stream *byte_stream) {}
+                                        grpc_byte_stream *byte_stream) {
+  grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+}
+
+static const grpc_byte_stream_vtable slice_buffer_stream_vtable = {
+    slice_buffer_stream_next, slice_buffer_stream_pull,
+    slice_buffer_stream_shutdown, slice_buffer_stream_destroy};
 
 void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
                                    grpc_slice_buffer *slice_buffer,
@@ -72,9 +98,89 @@
   GPR_ASSERT(slice_buffer->length <= UINT32_MAX);
   stream->base.length = (uint32_t)slice_buffer->length;
   stream->base.flags = flags;
-  stream->base.next = slice_buffer_stream_next;
-  stream->base.pull = slice_buffer_stream_pull;
-  stream->base.destroy = slice_buffer_stream_destroy;
+  stream->base.vtable = &slice_buffer_stream_vtable;
   stream->backing_buffer = slice_buffer;
   stream->cursor = 0;
+  stream->shutdown_error = GRPC_ERROR_NONE;
+}
+
+// grpc_caching_byte_stream
+
+void grpc_byte_stream_cache_init(grpc_byte_stream_cache *cache,
+                                 grpc_byte_stream *underlying_stream) {
+  cache->underlying_stream = underlying_stream;
+  grpc_slice_buffer_init(&cache->cache_buffer);
+}
+
+void grpc_byte_stream_cache_destroy(grpc_exec_ctx *exec_ctx,
+                                    grpc_byte_stream_cache *cache) {
+  grpc_byte_stream_destroy(exec_ctx, cache->underlying_stream);
+  grpc_slice_buffer_destroy_internal(exec_ctx, &cache->cache_buffer);
+}
+
+static bool caching_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                                     grpc_byte_stream *byte_stream,
+                                     size_t max_size_hint,
+                                     grpc_closure *on_complete) {
+  grpc_caching_byte_stream *stream = (grpc_caching_byte_stream *)byte_stream;
+  if (stream->shutdown_error != GRPC_ERROR_NONE) return true;
+  if (stream->cursor < stream->cache->cache_buffer.count) return true;
+  return grpc_byte_stream_next(exec_ctx, stream->cache->underlying_stream,
+                               max_size_hint, on_complete);
+}
+
+static grpc_error *caching_byte_stream_pull(grpc_exec_ctx *exec_ctx,
+                                            grpc_byte_stream *byte_stream,
+                                            grpc_slice *slice) {
+  grpc_caching_byte_stream *stream = (grpc_caching_byte_stream *)byte_stream;
+  if (stream->shutdown_error != GRPC_ERROR_NONE) {
+    return GRPC_ERROR_REF(stream->shutdown_error);
+  }
+  if (stream->cursor < stream->cache->cache_buffer.count) {
+    *slice = grpc_slice_ref_internal(
+        stream->cache->cache_buffer.slices[stream->cursor]);
+    ++stream->cursor;
+    return GRPC_ERROR_NONE;
+  }
+  grpc_error *error =
+      grpc_byte_stream_pull(exec_ctx, stream->cache->underlying_stream, slice);
+  if (error == GRPC_ERROR_NONE) {
+    ++stream->cursor;
+    grpc_slice_buffer_add(&stream->cache->cache_buffer,
+                          grpc_slice_ref_internal(*slice));
+  }
+  return error;
+}
+
+static void caching_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                                         grpc_byte_stream *byte_stream,
+                                         grpc_error *error) {
+  grpc_caching_byte_stream *stream = (grpc_caching_byte_stream *)byte_stream;
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+  stream->shutdown_error = GRPC_ERROR_REF(error);
+  grpc_byte_stream_shutdown(exec_ctx, stream->cache->underlying_stream, error);
+}
+
+static void caching_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
+                                        grpc_byte_stream *byte_stream) {
+  grpc_caching_byte_stream *stream = (grpc_caching_byte_stream *)byte_stream;
+  GRPC_ERROR_UNREF(stream->shutdown_error);
+}
+
+static const grpc_byte_stream_vtable caching_byte_stream_vtable = {
+    caching_byte_stream_next, caching_byte_stream_pull,
+    caching_byte_stream_shutdown, caching_byte_stream_destroy};
+
+void grpc_caching_byte_stream_init(grpc_caching_byte_stream *stream,
+                                   grpc_byte_stream_cache *cache) {
+  memset(stream, 0, sizeof(*stream));
+  stream->base.length = cache->underlying_stream->length;
+  stream->base.flags = cache->underlying_stream->flags;
+  stream->base.vtable = &caching_byte_stream_vtable;
+  stream->cache = cache;
+  stream->shutdown_error = GRPC_ERROR_NONE;
+}
+
+void grpc_caching_byte_stream_reset(grpc_caching_byte_stream *stream) {
+  stream->cursor = 0;
 }
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
index f172296..1e1e831 100644
--- a/src/core/lib/transport/byte_stream.h
+++ b/src/core/lib/transport/byte_stream.h
@@ -28,52 +28,109 @@
 /** Mask of all valid internal flags. */
 #define GRPC_WRITE_INTERNAL_USED_MASK (GRPC_WRITE_INTERNAL_COMPRESS)
 
-struct grpc_byte_stream;
 typedef struct grpc_byte_stream grpc_byte_stream;
 
-struct grpc_byte_stream {
-  uint32_t length;
-  uint32_t flags;
+typedef struct {
   bool (*next)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream,
                size_t max_size_hint, grpc_closure *on_complete);
   grpc_error *(*pull)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream,
                       grpc_slice *slice);
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream,
+                   grpc_error *error);
   void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream);
+} grpc_byte_stream_vtable;
+
+struct grpc_byte_stream {
+  uint32_t length;
+  uint32_t flags;
+  const grpc_byte_stream_vtable *vtable;
 };
 
-/* returns 1 if the bytes are available immediately (in which case
- * on_complete will not be called), 0 if the bytes will be available
- * asynchronously.
- *
- * max_size_hint can be set as a hint as to the maximum number
- * of bytes that would be acceptable to read.
- */
-int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                          grpc_byte_stream *byte_stream, size_t max_size_hint,
-                          grpc_closure *on_complete);
+// Returns true if the bytes are available immediately (in which case
+// on_complete will not be called), false if the bytes will be available
+// asynchronously.
+//
+// max_size_hint can be set as a hint as to the maximum number
+// of bytes that would be acceptable to read.
+bool grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
+                           grpc_byte_stream *byte_stream, size_t max_size_hint,
+                           grpc_closure *on_complete);
 
-/* returns the next slice in the byte stream when it is ready (indicated by
- * either grpc_byte_stream_next returning 1 or on_complete passed to
- * grpc_byte_stream_next is called).
- *
- * once a slice is returned into *slice, it is owned by the caller.
- */
+// Returns the next slice in the byte stream when it is ready (indicated by
+// either grpc_byte_stream_next returning true or on_complete passed to
+// grpc_byte_stream_next is called).
+//
+// Once a slice is returned into *slice, it is owned by the caller.
 grpc_error *grpc_byte_stream_pull(grpc_exec_ctx *exec_ctx,
                                   grpc_byte_stream *byte_stream,
                                   grpc_slice *slice);
 
+// Shuts down the byte stream.
+//
+// If there is a pending call to on_complete from grpc_byte_stream_next(),
+// it will be invoked with the error passed to grpc_byte_stream_shutdown().
+//
+// The next call to grpc_byte_stream_pull() (if any) will return the error
+// passed to grpc_byte_stream_shutdown().
+void grpc_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
+                               grpc_byte_stream *byte_stream,
+                               grpc_error *error);
+
 void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
                               grpc_byte_stream *byte_stream);
 
-/* grpc_byte_stream that wraps a slice buffer */
+// grpc_slice_buffer_stream
+//
+// A grpc_byte_stream that wraps a slice buffer.
+
 typedef struct grpc_slice_buffer_stream {
   grpc_byte_stream base;
   grpc_slice_buffer *backing_buffer;
   size_t cursor;
+  grpc_error *shutdown_error;
 } grpc_slice_buffer_stream;
 
 void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream,
                                    grpc_slice_buffer *slice_buffer,
                                    uint32_t flags);
 
+// grpc_caching_byte_stream
+//
+// A grpc_byte_stream that that wraps an underlying byte stream but caches
+// the resulting slices in a slice buffer.  If an initial attempt fails
+// without fully draining the underlying stream, a new caching stream
+// can be created from the same underlying cache, in which case it will
+// return whatever is in the backing buffer before continuing to read the
+// underlying stream.
+//
+// NOTE: No synchronization is done, so it is not safe to have multiple
+// grpc_caching_byte_streams simultaneously drawing from the same underlying
+// grpc_byte_stream_cache at the same time.
+
+typedef struct {
+  grpc_byte_stream *underlying_stream;
+  grpc_slice_buffer cache_buffer;
+} grpc_byte_stream_cache;
+
+// Takes ownership of underlying_stream.
+void grpc_byte_stream_cache_init(grpc_byte_stream_cache *cache,
+                                 grpc_byte_stream *underlying_stream);
+
+// Must not be called while still in use by a grpc_caching_byte_stream.
+void grpc_byte_stream_cache_destroy(grpc_exec_ctx *exec_ctx,
+                                    grpc_byte_stream_cache *cache);
+
+typedef struct {
+  grpc_byte_stream base;
+  grpc_byte_stream_cache *cache;
+  size_t cursor;
+  grpc_error *shutdown_error;
+} grpc_caching_byte_stream;
+
+void grpc_caching_byte_stream_init(grpc_caching_byte_stream *stream,
+                                   grpc_byte_stream_cache *cache);
+
+// Resets the byte stream to the start of the underlying stream.
+void grpc_caching_byte_stream_reset(grpc_caching_byte_stream *stream);
+
 #endif /* GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H */
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
index 6fe40af..73a9178 100644
--- a/src/core/lib/transport/connectivity_state.c
+++ b/src/core/lib/transport/connectivity_state.c
@@ -24,7 +24,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-grpc_tracer_flag grpc_connectivity_state_trace = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_connectivity_state_trace =
+    GRPC_TRACER_INITIALIZER(false, "connectivity_state");
 
 const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
   switch (state) {
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 87a2abf..2fea366 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -48,7 +48,8 @@
  */
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_metadata = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_metadata =
+    GRPC_TRACER_INITIALIZER(false, "metadata");
 #define DEBUG_ARGS , const char *file, int line
 #define FWD_DEBUG_ARGS , file, line
 #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__)
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
index 6a9eba1..6c61f4b 100644
--- a/src/core/lib/transport/transport.c
+++ b/src/core/lib/transport/transport.c
@@ -32,7 +32,8 @@
 #include "src/core/lib/transport/transport_impl.h"
 
 #ifndef NDEBUG
-grpc_tracer_flag grpc_trace_stream_refcount = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag grpc_trace_stream_refcount =
+    GRPC_TRACER_INITIALIZER(false, "stream_refcount");
 #endif
 
 #ifndef NDEBUG
@@ -206,27 +207,35 @@
   return transport->vtable->get_endpoint(exec_ctx, transport);
 }
 
+// This comment should be sung to the tune of
+// "Supercalifragilisticexpialidocious":
+//
 // grpc_transport_stream_op_batch_finish_with_failure
 // is a function that must always unref cancel_error
 // though it lives in lib, it handles transport stream ops sure
 // it's grpc_transport_stream_op_batch_finish_with_failure
 
 void grpc_transport_stream_op_batch_finish_with_failure(
-    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op,
+    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *batch,
     grpc_error *error) {
-  if (op->recv_message) {
-    GRPC_CLOSURE_SCHED(exec_ctx, op->payload->recv_message.recv_message_ready,
+  if (batch->send_message) {
+    grpc_byte_stream_destroy(exec_ctx,
+                             batch->payload->send_message.send_message);
+  }
+  if (batch->recv_message) {
+    GRPC_CLOSURE_SCHED(exec_ctx,
+                       batch->payload->recv_message.recv_message_ready,
                        GRPC_ERROR_REF(error));
   }
-  if (op->recv_initial_metadata) {
+  if (batch->recv_initial_metadata) {
     GRPC_CLOSURE_SCHED(
         exec_ctx,
-        op->payload->recv_initial_metadata.recv_initial_metadata_ready,
+        batch->payload->recv_initial_metadata.recv_initial_metadata_ready,
         GRPC_ERROR_REF(error));
   }
-  GRPC_CLOSURE_SCHED(exec_ctx, op->on_complete, error);
-  if (op->cancel_stream) {
-    GRPC_ERROR_UNREF(op->payload->cancel_stream.cancel_error);
+  GRPC_CLOSURE_SCHED(exec_ctx, batch->on_complete, error);
+  if (batch->cancel_stream) {
+    GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
   }
 }
 
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 84e53e6..099138e 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -159,6 +159,11 @@
   } send_trailing_metadata;
 
   struct {
+    // The transport (or a filter that decides to return a failure before
+    // the op gets down to the transport) is responsible for calling
+    // grpc_byte_stream_destroy() on this.
+    // The batch's on_complete will not be called until after the byte
+    // stream is destroyed.
     grpc_byte_stream *send_message;
   } send_message;
 
@@ -174,6 +179,10 @@
   } recv_initial_metadata;
 
   struct {
+    // Will be set by the transport to point to the byte stream
+    // containing a received message.
+    // The caller is responsible for calling grpc_byte_stream_destroy()
+    // on this byte stream.
     grpc_byte_stream **recv_message;
     /** Should be enqueued when one message is ready to be processed. */
     grpc_closure *recv_message_ready;
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.c b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
index b468c03..322ebea 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
@@ -26,6 +26,8 @@
 extern void grpc_deadline_filter_shutdown(void);
 extern void grpc_client_channel_init(void);
 extern void grpc_client_channel_shutdown(void);
+extern void grpc_tsi_gts_init(void);
+extern void grpc_tsi_gts_shutdown(void);
 extern void grpc_load_reporting_plugin_init(void);
 extern void grpc_load_reporting_plugin_shutdown(void);
 
@@ -38,6 +40,8 @@
                        grpc_deadline_filter_shutdown);
   grpc_register_plugin(grpc_client_channel_init,
                        grpc_client_channel_shutdown);
+  grpc_register_plugin(grpc_tsi_gts_init,
+                       grpc_tsi_gts_shutdown);
   grpc_register_plugin(grpc_load_reporting_plugin_init,
                        grpc_load_reporting_plugin_shutdown);
 }
diff --git a/src/core/plugin_registry/grpc_plugin_registry.c b/src/core/plugin_registry/grpc_plugin_registry.c
index a816186..fa99749 100644
--- a/src/core/plugin_registry/grpc_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_plugin_registry.c
@@ -22,10 +22,14 @@
 extern void grpc_http_filters_shutdown(void);
 extern void grpc_chttp2_plugin_init(void);
 extern void grpc_chttp2_plugin_shutdown(void);
+extern void grpc_tsi_gts_init(void);
+extern void grpc_tsi_gts_shutdown(void);
 extern void grpc_deadline_filter_init(void);
 extern void grpc_deadline_filter_shutdown(void);
 extern void grpc_client_channel_init(void);
 extern void grpc_client_channel_shutdown(void);
+extern void grpc_inproc_plugin_init(void);
+extern void grpc_inproc_plugin_shutdown(void);
 extern void grpc_resolver_fake_init(void);
 extern void grpc_resolver_fake_shutdown(void);
 extern void grpc_lb_policy_grpclb_init(void);
@@ -56,10 +60,14 @@
                        grpc_http_filters_shutdown);
   grpc_register_plugin(grpc_chttp2_plugin_init,
                        grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_tsi_gts_init,
+                       grpc_tsi_gts_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_inproc_plugin_init,
+                       grpc_inproc_plugin_shutdown);
   grpc_register_plugin(grpc_resolver_fake_init,
                        grpc_resolver_fake_shutdown);
   grpc_register_plugin(grpc_lb_policy_grpclb_init,
diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
index 809d444..7eb599d 100644
--- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c
@@ -26,6 +26,8 @@
 extern void grpc_deadline_filter_shutdown(void);
 extern void grpc_client_channel_init(void);
 extern void grpc_client_channel_shutdown(void);
+extern void grpc_inproc_plugin_init(void);
+extern void grpc_inproc_plugin_shutdown(void);
 extern void grpc_resolver_dns_ares_init(void);
 extern void grpc_resolver_dns_ares_shutdown(void);
 extern void grpc_resolver_dns_native_init(void);
@@ -60,6 +62,8 @@
                        grpc_deadline_filter_shutdown);
   grpc_register_plugin(grpc_client_channel_init,
                        grpc_client_channel_shutdown);
+  grpc_register_plugin(grpc_inproc_plugin_init,
+                       grpc_inproc_plugin_shutdown);
   grpc_register_plugin(grpc_resolver_dns_ares_init,
                        grpc_resolver_dns_ares_shutdown);
   grpc_register_plugin(grpc_resolver_dns_native_init,
diff --git a/src/core/tsi/gts_transport_security.c b/src/core/tsi/gts_transport_security.c
new file mode 100644
index 0000000..e2ac685
--- /dev/null
+++ b/src/core/tsi/gts_transport_security.c
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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 "src/core/tsi/gts_transport_security.h"
+
+#include <string.h>
+
+static gts_shared_resource g_gts_resource;
+
+gts_shared_resource *gts_get_shared_resource(void) { return &g_gts_resource; }
+
+void grpc_tsi_gts_init() {
+  memset(&g_gts_resource, 0, sizeof(gts_shared_resource));
+  gpr_mu_init(&g_gts_resource.mu);
+}
+
+void grpc_tsi_gts_shutdown() {
+  gpr_mu_destroy(&g_gts_resource.mu);
+  if (g_gts_resource.cq == NULL) {
+    return;
+  }
+  grpc_completion_queue_destroy(g_gts_resource.cq);
+  grpc_channel_destroy(g_gts_resource.channel);
+  gpr_thd_join(g_gts_resource.thread_id);
+}
diff --git a/src/core/tsi/gts_transport_security.h b/src/core/tsi/gts_transport_security.h
new file mode 100644
index 0000000..538e103
--- /dev/null
+++ b/src/core/tsi/gts_transport_security.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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_GTS_TRANSPORT_SECURITY_H
+#define GRPC_CORE_TSI_GTS_TRANSPORT_SECURITY_H
+
+#include <grpc/grpc.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+
+typedef struct gts_shared_resource {
+  gpr_thd_id thread_id;
+  grpc_channel *channel;
+  grpc_completion_queue *cq;
+  gpr_mu mu;
+} gts_shared_resource;
+
+/* This method returns the address of gts_shared_resource object shared by all
+ *    TSI handshakes. */
+gts_shared_resource *gts_get_shared_resource(void);
+
+#endif /* GRPC_CORE_TSI_GTS_TRANSPORT_SECURITY_H */
diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c
index 08fa431..be11d64 100644
--- a/src/core/tsi/transport_security.c
+++ b/src/core/tsi/transport_security.c
@@ -26,7 +26,7 @@
 
 /* --- Tracing. --- */
 
-grpc_tracer_flag tsi_tracing_enabled = GRPC_TRACER_INITIALIZER(false);
+grpc_tracer_flag tsi_tracing_enabled = GRPC_TRACER_INITIALIZER(false, "tsi");
 
 /* --- tsi_result common implementation. --- */
 
diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc
index 038eb32..f2d9bb0 100644
--- a/src/cpp/client/channel_cc.cc
+++ b/src/cpp/client/channel_cc.cc
@@ -76,9 +76,8 @@
                              &channel_info.service_config_json);
 }
 
-internal::Call Channel::CreateCall(const internal::RpcMethod& method,
-                                   ClientContext* context,
-                                   CompletionQueue* cq) {
+Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
+                         CompletionQueue* cq) {
   const bool kRegistered = method.channel_tag() && context->authority().empty();
   grpc_call* c_call = NULL;
   if (kRegistered) {
@@ -110,11 +109,10 @@
   }
   grpc_census_call_set_context(c_call, context->census_context());
   context->set_call(c_call, shared_from_this());
-  return internal::Call(c_call, this, cq);
+  return Call(c_call, this, cq);
 }
 
-void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                               internal::Call* call) {
+void Channel::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
   static const size_t MAX_OPS = 8;
   size_t nops = 0;
   grpc_op cops[MAX_OPS];
@@ -133,7 +131,7 @@
 }
 
 namespace {
-class TagSaver final : public internal::CompletionQueueTag {
+class TagSaver final : public CompletionQueueTag {
  public:
   explicit TagSaver(void* tag) : tag_(tag) {}
   ~TagSaver() override {}
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 14cacc8..3af8bdc 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -24,6 +24,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include <grpc++/impl/grpc_library.h>
 #include <grpc++/security/credentials.h>
 #include <grpc++/server_context.h>
 #include <grpc++/support/time.h>
@@ -38,6 +39,7 @@
   void Destructor(ClientContext* context) override {}
 };
 
+static internal::GrpcLibraryInitializer g_gli_initializer;
 static DefaultGlobalClientCallbacks g_default_client_callbacks;
 static ClientContext::GlobalCallbacks* g_client_callbacks =
     &g_default_client_callbacks;
diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc
index e65cb99..66b1ef0 100644
--- a/src/cpp/client/generic_stub.cc
+++ b/src/cpp/client/generic_stub.cc
@@ -27,11 +27,9 @@
     ClientContext* context, const grpc::string& method, CompletionQueue* cq,
     void* tag) {
   return std::unique_ptr<GenericClientAsyncReaderWriter>(
-      GenericClientAsyncReaderWriter::internal::Create(
+      GenericClientAsyncReaderWriter::Create(
           channel_.get(), cq,
-          internal::RpcMethod(method.c_str(),
-                              internal::RpcMethod::BIDI_STREAMING),
-          context, tag));
+          RpcMethod(method.c_str(), RpcMethod::BIDI_STREAMING), context, tag));
 }
 
 }  // namespace grpc
diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc
index 000a032..f34b0f3 100644
--- a/src/cpp/common/completion_queue_cc.cc
+++ b/src/cpp/common/completion_queue_cc.cc
@@ -60,7 +60,7 @@
       case GRPC_QUEUE_SHUTDOWN:
         return SHUTDOWN;
       case GRPC_OP_COMPLETE:
-        auto cq_tag = static_cast<internal::CompletionQueueTag*>(ev.tag);
+        auto cq_tag = static_cast<CompletionQueueTag*>(ev.tag);
         *ok = ev.success != 0;
         *tag = cq_tag;
         if (cq_tag->FinalizeResult(tag, ok)) {
diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc
index 7101740..c7c6b6b 100644
--- a/src/cpp/common/core_codegen.cc
+++ b/src/cpp/common/core_codegen.cc
@@ -93,6 +93,11 @@
   ::grpc_byte_buffer_destroy(bb);
 }
 
+grpc_call_error CoreCodegen::grpc_call_cancel_with_status(
+    grpc_call* call, grpc_status_code status, const char* description,
+    void* reserved) {
+  return ::grpc_call_cancel_with_status(call, status, description, reserved);
+}
 void CoreCodegen::grpc_call_ref(grpc_call* call) { ::grpc_call_ref(call); }
 void CoreCodegen::grpc_call_unref(grpc_call* call) { ::grpc_call_unref(call); }
 void* CoreCodegen::grpc_call_arena_alloc(grpc_call* call, size_t length) {
diff --git a/src/cpp/server/create_default_thread_pool.cc b/src/cpp/server/create_default_thread_pool.cc
index 17ad331..8ca3e32 100644
--- a/src/cpp/server/create_default_thread_pool.cc
+++ b/src/cpp/server/create_default_thread_pool.cc
@@ -23,13 +23,22 @@
 #ifndef GRPC_CUSTOM_DEFAULT_THREAD_POOL
 
 namespace grpc {
+namespace {
 
-ThreadPoolInterface* CreateDefaultThreadPool() {
+ThreadPoolInterface* CreateDefaultThreadPoolImpl() {
   int cores = gpr_cpu_num_cores();
   if (!cores) cores = 4;
   return new DynamicThreadPool(cores);
 }
 
+CreateThreadPoolFunc g_ctp_impl = CreateDefaultThreadPoolImpl;
+
+}  // namespace
+
+ThreadPoolInterface* CreateDefaultThreadPool() { return g_ctp_impl(); }
+
+void SetCreateThreadPool(CreateThreadPoolFunc func) { g_ctp_impl = func; }
+
 }  // namespace grpc
 
 #endif  // !GRPC_CUSTOM_DEFAULT_THREAD_POOL
diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc
index fc7feb7..815b607 100644
--- a/src/cpp/server/health/default_health_check_service.cc
+++ b/src/cpp/server/health/default_health_check_service.cc
@@ -36,12 +36,11 @@
 DefaultHealthCheckService::HealthCheckServiceImpl::HealthCheckServiceImpl(
     DefaultHealthCheckService* service)
     : service_(service), method_(nullptr) {
-  internal::MethodHandler* handler =
-      new internal::RpcMethodHandler<HealthCheckServiceImpl, ByteBuffer,
-                                     ByteBuffer>(
+  MethodHandler* handler =
+      new RpcMethodHandler<HealthCheckServiceImpl, ByteBuffer, ByteBuffer>(
           std::mem_fn(&HealthCheckServiceImpl::Check), this);
-  method_ = new internal::RpcServiceMethod(
-      kHealthCheckMethodName, internal::RpcMethod::NORMAL_RPC, handler);
+  method_ = new RpcServiceMethod(kHealthCheckMethodName, RpcMethod::NORMAL_RPC,
+                                 handler);
   AddMethod(method_);
 }
 
diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h
index 99d6680..09d5ceb 100644
--- a/src/cpp/server/health/default_health_check_service.h
+++ b/src/cpp/server/health/default_health_check_service.h
@@ -41,7 +41,7 @@
 
    private:
     const DefaultHealthCheckService* const service_;
-    internal::RpcServiceMethod* method_;
+    RpcServiceMethod* method_;
   };
 
   DefaultHealthCheckService();
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index c90f96c..200e477 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -250,14 +250,6 @@
       has_sync_methods && num_frequently_polled_cqs > 0;
 
   if (has_sync_methods) {
-    // This is a Sync server
-    gpr_log(GPR_INFO,
-            "Synchronous server. Num CQs: %d, Min pollers: %d, Max Pollers: "
-            "%d, CQ timeout (msec): %d",
-            sync_server_settings_.num_cqs, sync_server_settings_.min_pollers,
-            sync_server_settings_.max_pollers,
-            sync_server_settings_.cq_timeout_msec);
-
     grpc_cq_polling_type polling_type =
         is_hybrid_server ? GRPC_CQ_NON_POLLING : GRPC_CQ_DEFAULT_POLLING;
 
@@ -272,6 +264,16 @@
       sync_server_settings_.min_pollers, sync_server_settings_.max_pollers,
       sync_server_settings_.cq_timeout_msec));
 
+  if (has_sync_methods) {
+    // This is a Sync server
+    gpr_log(GPR_INFO,
+            "Synchronous server. Num CQs: %d, Min pollers: %d, Max Pollers: "
+            "%d, CQ timeout (msec): %d",
+            sync_server_settings_.num_cqs, sync_server_settings_.min_pollers,
+            sync_server_settings_.max_pollers,
+            sync_server_settings_.cq_timeout_msec);
+  }
+
   ServerInitializer* initializer = server->initializer();
 
   // Register all the completion queues with the server. i.e
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 3bff999..2483300 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -36,7 +36,9 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
+#include "src/core/ext/transport/inproc/inproc_transport.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
 #include "src/cpp/server/health/default_health_check_service.h"
 #include "src/cpp/thread_manager/thread_manager.h"
 
@@ -86,8 +88,7 @@
   ServerCompletionQueue* const cq_;
 };
 
-typedef internal::SneakyCallOpSet<internal::CallOpSendInitialMetadata,
-                                  internal::CallOpServerSendStatus>
+typedef SneakyCallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus>
     UnimplementedAsyncResponseOp;
 class Server::UnimplementedAsyncResponse final
     : public UnimplementedAsyncResponseOp {
@@ -105,12 +106,12 @@
   UnimplementedAsyncRequest* const request_;
 };
 
-class ShutdownTag : public internal::CompletionQueueTag {
+class ShutdownTag : public CompletionQueueTag {
  public:
   bool FinalizeResult(void** tag, bool* status) { return false; }
 };
 
-class DummyTag : public internal::CompletionQueueTag {
+class DummyTag : public CompletionQueueTag {
  public:
   bool FinalizeResult(void** tag, bool* status) {
     *status = true;
@@ -118,15 +119,15 @@
   }
 };
 
-class Server::SyncRequest final : public internal::CompletionQueueTag {
+class Server::SyncRequest final : public CompletionQueueTag {
  public:
-  SyncRequest(internal::RpcServiceMethod* method, void* tag)
+  SyncRequest(RpcServiceMethod* method, void* tag)
       : method_(method),
         tag_(tag),
         in_flight_(false),
-        has_request_payload_(
-            method->method_type() == internal::RpcMethod::NORMAL_RPC ||
-            method->method_type() == internal::RpcMethod::SERVER_STREAMING),
+        has_request_payload_(method->method_type() == RpcMethod::NORMAL_RPC ||
+                             method->method_type() ==
+                                 RpcMethod::SERVER_STREAMING),
         call_details_(nullptr),
         cq_(nullptr) {
     grpc_metadata_array_init(&request_metadata_);
@@ -150,19 +151,25 @@
     GPR_ASSERT(cq_ && !in_flight_);
     in_flight_ = true;
     if (tag_) {
-      GPR_ASSERT(GRPC_CALL_OK ==
-                 grpc_server_request_registered_call(
-                     server, tag_, &call_, &deadline_, &request_metadata_,
-                     has_request_payload_ ? &request_payload_ : nullptr, cq_,
-                     notify_cq, this));
+      if (GRPC_CALL_OK !=
+          grpc_server_request_registered_call(
+              server, tag_, &call_, &deadline_, &request_metadata_,
+              has_request_payload_ ? &request_payload_ : nullptr, cq_,
+              notify_cq, this)) {
+        TeardownRequest();
+        return;
+      }
     } else {
       if (!call_details_) {
         call_details_ = new grpc_call_details;
         grpc_call_details_init(call_details_);
       }
-      GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
-                                     server, &call_, call_details_,
-                                     &request_metadata_, cq_, notify_cq, this));
+      if (grpc_server_request_call(server, &call_, call_details_,
+                                   &request_metadata_, cq_, notify_cq,
+                                   this) != GRPC_CALL_OK) {
+        TeardownRequest();
+        return;
+      }
     }
   }
 
@@ -203,14 +210,14 @@
     void Run(std::shared_ptr<GlobalCallbacks> global_callbacks) {
       ctx_.BeginCompletionOp(&call_);
       global_callbacks->PreSynchronousRequest(&ctx_);
-      method_->handler()->RunHandler(internal::MethodHandler::HandlerParameter(
-          &call_, &ctx_, request_payload_));
+      method_->handler()->RunHandler(
+          MethodHandler::HandlerParameter(&call_, &ctx_, request_payload_));
       global_callbacks->PostSynchronousRequest(&ctx_);
       request_payload_ = nullptr;
 
       cq_.Shutdown();
 
-      internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag();
+      CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag();
       cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME));
 
       /* Ensure the cq_ is shutdown */
@@ -220,15 +227,15 @@
 
    private:
     CompletionQueue cq_;
-    internal::Call call_;
+    Call call_;
     ServerContext ctx_;
     const bool has_request_payload_;
     grpc_byte_buffer* request_payload_;
-    internal::RpcServiceMethod* const method_;
+    RpcServiceMethod* const method_;
   };
 
  private:
-  internal::RpcServiceMethod* const method_;
+  RpcServiceMethod* const method_;
   void* const tag_;
   bool in_flight_;
   const bool has_request_payload_;
@@ -285,12 +292,10 @@
     if (ok) {
       // Calldata takes ownership of the completion queue inside sync_req
       SyncRequest::CallData cd(server_, sync_req);
-      {
-        // Prepare for the next request
-        if (!IsShutdown()) {
-          sync_req->SetupRequest();  // Create new completion queue for sync_req
-          sync_req->Request(server_->c_server(), server_cq_->cq());
-        }
+      // Prepare for the next request
+      if (!IsShutdown()) {
+        sync_req->SetupRequest();  // Create new completion queue for sync_req
+        sync_req->Request(server_->c_server(), server_cq_->cq());
       }
 
       GPR_TIMER_SCOPE("cd.Run()", 0);
@@ -301,23 +306,22 @@
     // object
   }
 
-  void AddSyncMethod(internal::RpcServiceMethod* method, void* tag) {
+  void AddSyncMethod(RpcServiceMethod* method, void* tag) {
     sync_requests_.emplace_back(new SyncRequest(method, tag));
   }
 
   void AddUnknownSyncMethod() {
     if (!sync_requests_.empty()) {
-      unknown_method_.reset(new internal::RpcServiceMethod(
-          "unknown", internal::RpcMethod::BIDI_STREAMING,
-          new internal::UnknownMethodHandler));
+      unknown_method_.reset(new RpcServiceMethod(
+          "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
       sync_requests_.emplace_back(
           new SyncRequest(unknown_method_.get(), nullptr));
     }
   }
 
   void Shutdown() override {
-    server_cq_->Shutdown();
     ThreadManager::Shutdown();
+    server_cq_->Shutdown();
   }
 
   void Wait() override {
@@ -346,8 +350,8 @@
   CompletionQueue* server_cq_;
   int cq_timeout_msec_;
   std::vector<std::unique_ptr<SyncRequest>> sync_requests_;
-  std::unique_ptr<internal::RpcServiceMethod> unknown_method_;
-  std::unique_ptr<internal::RpcServiceMethod> health_check_;
+  std::unique_ptr<RpcServiceMethod> unknown_method_;
+  std::unique_ptr<RpcServiceMethod> health_check_;
   std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
 };
 
@@ -422,14 +426,21 @@
 
 grpc_server* Server::c_server() { return server_; }
 
+std::shared_ptr<Channel> Server::InProcessChannel(
+    const ChannelArguments& args) {
+  grpc_channel_args channel_args = args.c_channel_args();
+  return CreateChannelInternal(
+      "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr));
+}
+
 static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
-    internal::RpcServiceMethod* method) {
+    RpcServiceMethod* method) {
   switch (method->method_type()) {
-    case internal::RpcMethod::NORMAL_RPC:
-    case internal::RpcMethod::SERVER_STREAMING:
+    case RpcMethod::NORMAL_RPC:
+    case RpcMethod::SERVER_STREAMING:
       return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
-    case internal::RpcMethod::CLIENT_STREAMING:
-    case internal::RpcMethod::BIDI_STREAMING:
+    case RpcMethod::CLIENT_STREAMING:
+    case RpcMethod::BIDI_STREAMING:
       return GRPC_SRM_PAYLOAD_NONE;
   }
   GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
@@ -450,7 +461,7 @@
       continue;
     }
 
-    internal::RpcServiceMethod* method = it->get();
+    RpcServiceMethod* method = it->get();
     void* tag = grpc_server_register_method(
         server_, method->name(), host ? host->c_str() : nullptr,
         PayloadHandlingForMethod(method), 0);
@@ -590,8 +601,7 @@
   }
 }
 
-void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops,
-                              internal::Call* call) {
+void Server::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
   static const size_t MAX_OPS = 8;
   size_t nops = 0;
   grpc_op cops[MAX_OPS];
@@ -602,8 +612,8 @@
 
 ServerInterface::BaseAsyncRequest::BaseAsyncRequest(
     ServerInterface* server, ServerContext* context,
-    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-    void* tag, bool delete_on_finalize)
+    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag,
+    bool delete_on_finalize)
     : server_(server),
       context_(context),
       stream_(stream),
@@ -625,8 +635,7 @@
   }
   context_->set_call(call_);
   context_->cq_ = call_cq_;
-  internal::Call call(call_, server_, call_cq_,
-                      server_->max_receive_message_size());
+  Call call(call_, server_, call_cq_, server_->max_receive_message_size());
   if (*status && call_) {
     context_->BeginCompletionOp(&call);
   }
@@ -641,31 +650,32 @@
 
 ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
     ServerInterface* server, ServerContext* context,
-    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-    void* tag)
+    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag)
     : BaseAsyncRequest(server, context, stream, call_cq, tag, true) {}
 
 void ServerInterface::RegisteredAsyncRequest::IssueRequest(
     void* registered_method, grpc_byte_buffer** payload,
     ServerCompletionQueue* notification_cq) {
-  grpc_server_request_registered_call(
-      server_->server(), registered_method, &call_, &context_->deadline_,
-      context_->client_metadata_.arr(), payload, call_cq_->cq(),
-      notification_cq->cq(), this);
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call(
+                                 server_->server(), registered_method, &call_,
+                                 &context_->deadline_,
+                                 context_->client_metadata_.arr(), payload,
+                                 call_cq_->cq(), notification_cq->cq(), this));
 }
 
 ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
     ServerInterface* server, GenericServerContext* context,
-    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
     ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
     : BaseAsyncRequest(server, context, stream, call_cq, tag,
                        delete_on_finalize) {
   grpc_call_details_init(&call_details_);
   GPR_ASSERT(notification_cq);
   GPR_ASSERT(call_cq);
-  grpc_server_request_call(server->server(), &call_, &call_details_,
-                           context->client_metadata_.arr(), call_cq->cq(),
-                           notification_cq->cq(), this);
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 server->server(), &call_, &call_details_,
+                                 context->client_metadata_.arr(), call_cq->cq(),
+                                 notification_cq->cq(), this));
 }
 
 bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
@@ -698,7 +708,7 @@
     UnimplementedAsyncRequest* request)
     : request_(request) {
   Status status(StatusCode::UNIMPLEMENTED, "");
-  internal::UnknownMethodHandler::FillOps(request_->context(), this);
+  UnknownMethodHandler::FillOps(request_->context(), this);
   request_->stream()->call_.PerformOps(this);
 }
 
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 2e55ffb..4913682 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -37,7 +37,7 @@
 
 // CompletionOp
 
-class ServerContext::CompletionOp final : public internal::CallOpSetInterface {
+class ServerContext::CompletionOp final : public CallOpSetInterface {
  public:
   // initial refs: one in the server context, one in the cq
   CompletionOp()
@@ -146,7 +146,7 @@
   }
 }
 
-void ServerContext::BeginCompletionOp(internal::Call* call) {
+void ServerContext::BeginCompletionOp(Call* call) {
   GPR_ASSERT(!completion_op_);
   completion_op_ = new CompletionOp();
   if (has_notify_when_done_tag_) {
@@ -155,8 +155,8 @@
   call->PerformOps(completion_op_);
 }
 
-internal::CompletionQueueTag* ServerContext::GetCompletionOpTag() {
-  return static_cast<internal::CompletionQueueTag*>(completion_op_);
+CompletionQueueTag* ServerContext::GetCompletionOpTag() {
+  return static_cast<CompletionQueueTag*>(completion_op_);
 }
 
 void ServerContext::AddInitialMetadata(const grpc::string& key,
diff --git a/src/cpp/server/thread_pool_interface.h b/src/cpp/server/thread_pool_interface.h
index 4f4fc7e..028842a 100644
--- a/src/cpp/server/thread_pool_interface.h
+++ b/src/cpp/server/thread_pool_interface.h
@@ -32,6 +32,10 @@
   virtual void Add(const std::function<void()>& callback) = 0;
 };
 
+// Allows different codebases to use their own thread pool impls
+typedef ThreadPoolInterface* (*CreateThreadPoolFunc)(void);
+void SetCreateThreadPool(CreateThreadPoolFunc func);
+
 ThreadPoolInterface* CreateDefaultThreadPool();
 
 }  // namespace grpc
diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc
index c0e860d..3610aa9 100644
--- a/src/cpp/thread_manager/thread_manager.cc
+++ b/src/cpp/thread_manager/thread_manager.cc
@@ -27,14 +27,23 @@
 namespace grpc {
 
 ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
-    : thd_mgr_(thd_mgr), thd_(&ThreadManager::WorkerThread::Run, this) {}
+    : thd_mgr_(thd_mgr) {
+  // Make thread creation exclusive with respect to its join happening in
+  // ~WorkerThread().
+  std::lock_guard<std::mutex> lock(wt_mu_);
+  thd_ = std::thread(&ThreadManager::WorkerThread::Run, this);
+}
 
 void ThreadManager::WorkerThread::Run() {
   thd_mgr_->MainWorkLoop();
   thd_mgr_->MarkAsCompleted(this);
 }
 
-ThreadManager::WorkerThread::~WorkerThread() { thd_.join(); }
+ThreadManager::WorkerThread::~WorkerThread() {
+  // Don't join until the thread is fully constructed.
+  std::lock_guard<std::mutex> lock(wt_mu_);
+  thd_.join();
+}
 
 ThreadManager::ThreadManager(int min_pollers, int max_pollers)
     : shutdown_(false),
@@ -45,7 +54,7 @@
 
 ThreadManager::~ThreadManager() {
   {
-    std::unique_lock<std::mutex> lock(mu_);
+    std::lock_guard<std::mutex> lock(mu_);
     GPR_ASSERT(num_threads_ == 0);
   }
 
@@ -60,22 +69,22 @@
 }
 
 void ThreadManager::Shutdown() {
-  std::unique_lock<std::mutex> lock(mu_);
+  std::lock_guard<std::mutex> lock(mu_);
   shutdown_ = true;
 }
 
 bool ThreadManager::IsShutdown() {
-  std::unique_lock<std::mutex> lock(mu_);
+  std::lock_guard<std::mutex> lock(mu_);
   return shutdown_;
 }
 
 void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
   {
-    std::unique_lock<std::mutex> list_lock(list_mu_);
+    std::lock_guard<std::mutex> list_lock(list_mu_);
     completed_threads_.push_back(thd);
   }
 
-  std::unique_lock<std::mutex> lock(mu_);
+  std::lock_guard<std::mutex> lock(mu_);
   num_threads_--;
   if (num_threads_ == 0) {
     shutdown_cv_.notify_one();
diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h
index d714ef3..a206e0b 100644
--- a/src/cpp/thread_manager/thread_manager.h
+++ b/src/cpp/thread_manager/thread_manager.h
@@ -100,7 +100,8 @@
     // thd_mgr_>MarkAsCompleted(this) to mark the thread as completed
     void Run();
 
-    ThreadManager* thd_mgr_;
+    ThreadManager* const thd_mgr_;
+    std::mutex wt_mu_;
     std::thread thd_;
   };
 
diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc
index 80b4b3a..56e0328 100644
--- a/src/cpp/util/slice_cc.cc
+++ b/src/cpp/util/slice_cc.cc
@@ -28,6 +28,19 @@
 
 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(reinterpret_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(reinterpret_cast<const char*>(buf),
+                                           len)) {}
+
 Slice::Slice(const Slice& other) : slice_(grpc_slice_ref(other.slice_)) {}
 
 }  // namespace grpc
diff --git a/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs b/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs
new file mode 100644
index 0000000..fb18198
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs
@@ -0,0 +1,98 @@
+#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 NUnit.Framework;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Grpc.Core.Tests
+{
+    public class ThreadingModelTest
+    {
+        const string Host = "127.0.0.1";
+
+        MockServiceHelper helper;
+        Server server;
+        Channel channel;
+
+        [SetUp]
+        public void Init()
+        {
+            helper = new MockServiceHelper(Host);
+            server = helper.GetServer();
+            server.Start();
+            channel = helper.GetChannel();
+        }
+
+        [TearDown]
+        public void Cleanup()
+        {
+            channel.ShutdownAsync().Wait();
+            server.ShutdownAsync().Wait();
+        }
+
+        [Test]
+        public void BlockingCallInServerHandlerDoesNotDeadlock()
+        {
+            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
+            {
+                int recursionDepth = int.Parse(request);
+                if (recursionDepth <= 0) {
+                    return "SUCCESS";
+                }
+                return Calls.BlockingUnaryCall(helper.CreateUnaryCall(), (recursionDepth - 1).ToString());
+            });
+
+            int maxRecursionDepth = Environment.ProcessorCount * 2;  // make sure we have more pending blocking calls than threads in GrpcThreadPool
+            Assert.AreEqual("SUCCESS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), maxRecursionDepth.ToString()));
+        }
+
+        [Test]
+        public void HandlerDoesNotRunOnGrpcThread()
+        {
+            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
+            {
+                if (IsRunningOnGrpcThreadPool()) {
+                    return "Server handler should not run on gRPC threadpool thread.";
+                }
+                return request;
+            });
+
+            Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
+        }
+
+        [Test]
+        public async Task ContinuationDoesNotRunOnGrpcThread()
+        {
+            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
+            {
+                return request;
+            });
+
+            await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC");
+            Assert.IsFalse(IsRunningOnGrpcThreadPool());
+        }
+
+        private static bool IsRunningOnGrpcThreadPool()
+        {
+            var threadName = Thread.CurrentThread.Name ?? "";
+            return threadName.Contains("grpc");
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 5035829..e32711c 100755
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -64,6 +64,7 @@
   <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
     <PackageReference Include="System.Runtime.Loader" Version="4.0.0" />
     <PackageReference Include="System.Threading.Thread" Version="4.0.0" />
+    <PackageReference Include="System.Threading.ThreadPool" Version="4.0.0" />
   </ItemGroup>
 
   <Import Project="NativeDeps.csproj.include" />
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index 8d0c66a..0663ee9 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -39,6 +39,7 @@
         static int refCount;
         static int? customThreadPoolSize;
         static int? customCompletionQueueCount;
+        static bool inlineHandlers;
         static readonly HashSet<Channel> registeredChannels = new HashSet<Channel>();
         static readonly HashSet<Server> registeredServers = new HashSet<Server>();
 
@@ -218,12 +219,31 @@
         }
 
         /// <summary>
+        /// By default, gRPC's internal event handlers get offloaded to .NET default thread pool thread (<c>inlineHandlers=false</c>).
+        /// Setting <c>inlineHandlers</c> to <c>true</c> will allow scheduling the event handlers directly to
+        /// <c>GrpcThreadPool</c> internal threads. That can lead to significant performance gains in some situations,
+        /// but requires user to never block in async code (incorrectly written code can easily lead to deadlocks).
+        /// Inlining handlers is an advanced setting and you should only use it if you know what you are doing.
+        /// Most users should rely on the default value provided by gRPC library.
+        /// Note: this method is part of an experimental API that can change or be removed without any prior notice.
+        /// Note: <c>inlineHandlers=true</c> was the default in gRPC C# v1.4.x and earlier.
+        /// </summary>
+        public static void SetHandlerInlining(bool inlineHandlers)
+        {
+            lock (staticLock)
+            {
+                GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized");
+                GrpcEnvironment.inlineHandlers = inlineHandlers;
+            }
+        }
+
+        /// <summary>
         /// Creates gRPC environment.
         /// </summary>
         private GrpcEnvironment()
         {
             GrpcNativeInit();
-            threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault());
+            threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault(), inlineHandlers);
             threadPool.Start();
         }
 
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index f9ae77c..19b44c2 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -33,12 +33,15 @@
     internal class GrpcThreadPool
     {
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<GrpcThreadPool>();
+        static readonly WaitCallback RunCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, true));
+        static readonly WaitCallback RunCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, false));
 
         readonly GrpcEnvironment environment;
         readonly object myLock = new object();
         readonly List<Thread> threads = new List<Thread>();
         readonly int poolSize;
         readonly int completionQueueCount;
+        readonly bool inlineHandlers;
 
         readonly List<BasicProfiler> threadProfilers = new List<BasicProfiler>();  // profilers assigned to threadpool threads
 
@@ -52,11 +55,13 @@
         /// <param name="environment">Environment.</param>
         /// <param name="poolSize">Pool size.</param>
         /// <param name="completionQueueCount">Completion queue count.</param>
-        public GrpcThreadPool(GrpcEnvironment environment, int poolSize, int completionQueueCount)
+        /// <param name="inlineHandlers">Handler inlining.</param>
+        public GrpcThreadPool(GrpcEnvironment environment, int poolSize, int completionQueueCount, bool inlineHandlers)
         {
             this.environment = environment;
             this.poolSize = poolSize;
             this.completionQueueCount = completionQueueCount;
+            this.inlineHandlers = inlineHandlers;
             GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount,
                 "Thread pool size cannot be smaller than the number of completion queues used.");
         }
@@ -165,11 +170,19 @@
                     try
                     {
                         var callback = cq.CompletionRegistry.Extract(tag);
-                        callback(success);
+                        // Use cached delegates to avoid unnecessary allocations
+                        if (!inlineHandlers)
+                        {
+                            ThreadPool.QueueUserWorkItem(success ? RunCompletionQueueEventCallbackSuccess : RunCompletionQueueEventCallbackFailure, callback);
+                        }
+                        else
+                        {
+                            RunCompletionQueueEventCallback(callback, success);
+                        }
                     }
                     catch (Exception e)
                     {
-                        Logger.Error(e, "Exception occured while invoking completion delegate");
+                        Logger.Error(e, "Exception occured while extracting event from completion registry.");
                     }
                 }
             }
@@ -186,5 +199,17 @@
             }
             return list.AsReadOnly();
         }
+
+        private static void RunCompletionQueueEventCallback(OpCompletionDelegate callback, bool success)
+        {
+            try
+            {
+                callback(success);
+            }
+            catch (Exception e)
+            {
+                Logger.Error(e, "Exception occured while invoking completion delegate");
+            }
+        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index 7009a93..a579fb8 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -63,11 +63,6 @@
 
         private async Task RunAsync()
         {
-            // (ThreadPoolSize == ProcessorCount) gives best throughput in benchmarks
-            // and doesn't seem to harm performance even when server and client
-            // are running on the same machine.
-            GrpcEnvironment.SetThreadPoolSize(Environment.ProcessorCount);
-
             string host = "0.0.0.0";
             int port = options.DriverPort;
 
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
index bc6adbb..7841051 100644
--- a/src/csharp/tests.json
+++ b/src/csharp/tests.json
@@ -31,6 +31,7 @@
     "Grpc.Core.Tests.ShutdownHookPendingCallTest",
     "Grpc.Core.Tests.ShutdownHookServerTest",
     "Grpc.Core.Tests.ShutdownTest",
+    "Grpc.Core.Tests.ThreadingModelTest",
     "Grpc.Core.Tests.TimeoutsTest",
     "Grpc.Core.Tests.UserAgentStringTest"
   ],
diff --git a/src/node/src/server.js b/src/node/src/server.js
index fba0aac..8b7c0b6 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -919,11 +919,6 @@
   });
 };
 
-var logAddProtoServiceDeprecationOnce = _.once(function() {
-    common.log(constants.logVerbosity.INFO,
-               'Server#addProtoService is deprecated. Use addService instead');
-});
-
 /**
  * Add a proto service to the server, with a corresponding implementation
  * @deprecated Use {@link grpc.Server#addService} instead
@@ -931,11 +926,11 @@
  * @param {Object<String, grpc.Server~handleCall>} implementation Map of method
  *     names to method implementation for the provided service.
  */
-Server.prototype.addProtoService = function(service, implementation) {
+Server.prototype.addProtoService = util.deprecate(function(service,
+                                                           implementation) {
   var options;
   var protobuf_js_5_common = require('./protobuf_js_5_common');
   var protobuf_js_6_common = require('./protobuf_js_6_common');
-  logAddProtoServiceDeprecationOnce();
   if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {
     options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
     this.addService(
@@ -950,7 +945,7 @@
     // We assume that this is a service attributes object
     this.addService(service, implementation);
   }
-};
+}, 'Server#addProtoService: Use Server#addService instead');
 
 /**
  * Binds the server to the given port, with SSL disabled if creds is an
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 3688f03..0ff838e 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -319,7 +319,9 @@
                             client_options);
     client.unary({}, function(err, data) {
       assert(err);
-      assert.strictEqual(err.message, 'Authentication error');
+      assert.strictEqual(err.message,
+                         'Getting metadata from plugin failed with error: ' +
+                         'Authentication error');
       assert.strictEqual(err.code, grpc.status.UNAUTHENTICATED);
       done();
     });
@@ -367,7 +369,9 @@
                             client_options);
     client.unary({}, function(err, data) {
       assert(err);
-      assert.strictEqual(err.message, 'Authentication failure');
+      assert.strictEqual(err.message,
+                         'Getting metadata from plugin failed with error: ' +
+                         'Authentication failure');
       done();
     });
   });
diff --git "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec" "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
index 22527d1..345eecc 100644
--- "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
+++ "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
@@ -101,7 +101,7 @@
   s.preserve_paths = plugin
 
   # Restrict the protoc version to the one supported by this plugin.
-  s.dependency '!ProtoCompiler', '3.2.0'
+  s.dependency '!ProtoCompiler', '3.3.0'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.9'
diff --git "a/src/objective-c/\041ProtoCompiler.podspec" "b/src/objective-c/\041ProtoCompiler.podspec"
index 2e9b944..c3f95f9 100644
--- "a/src/objective-c/\041ProtoCompiler.podspec"
+++ "b/src/objective-c/\041ProtoCompiler.podspec"
@@ -36,7 +36,7 @@
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler'
-  v = '3.2.0'
+  v = '3.3.0'
   s.version  = v
   s.summary  = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
   s.description = <<-DESC
diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec
index 651bd49..37798ec 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 = '8.2'
+  version = '9.0'
   s.version  = version
   s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
   # Adapted from the homepage:
@@ -69,9 +69,7 @@
 
   s.source = {
     :git => 'https://boringssl.googlesource.com/boringssl',
-    # Restore this version name hack in the next version!!
-    # :tag => "version_for_cocoapods_#{version}",
-    :tag => "version_for_cocoapods_8.0",
+    :tag => "version_for_cocoapods_#{version}",
   }
 
   name = 'openssl'
@@ -169,7 +167,6 @@
       #include "hkdf.h"
       #include "md4.h"
       #include "md5.h"
-      #include "newhope.h"
       #include "obj_mac.h"
       #include "objects.h"
       #include "opensslv.h"
@@ -183,7 +180,6 @@
       #include "ripemd.h"
       #include "safestack.h"
       #include "srtp.h"
-      #include "time_support.h"
       #include "x509.h"
       #include "x509v3.h"
     EOF
@@ -389,42 +385,42 @@
           0x28340c19,
           0x283480ac,
           0x283500ea,
-          0x2c3228ca,
-          0x2c32a8d8,
-          0x2c3328ea,
-          0x2c33a8fc,
-          0x2c342910,
-          0x2c34a922,
-          0x2c35293d,
-          0x2c35a94f,
-          0x2c362962,
+          0x2c3229b1,
+          0x2c32a9bf,
+          0x2c3329d1,
+          0x2c33a9e3,
+          0x2c3429f7,
+          0x2c34aa09,
+          0x2c352a24,
+          0x2c35aa36,
+          0x2c362a49,
           0x2c36832d,
-          0x2c37296f,
-          0x2c37a981,
-          0x2c382994,
-          0x2c38a9ab,
-          0x2c3929b9,
-          0x2c39a9c9,
-          0x2c3a29db,
-          0x2c3aa9ef,
-          0x2c3b2a00,
-          0x2c3baa1f,
-          0x2c3c2a33,
-          0x2c3caa49,
-          0x2c3d2a62,
-          0x2c3daa7f,
-          0x2c3e2a90,
-          0x2c3eaa9e,
-          0x2c3f2ab6,
-          0x2c3faace,
-          0x2c402adb,
+          0x2c372a56,
+          0x2c37aa68,
+          0x2c382a7b,
+          0x2c38aa92,
+          0x2c392aa0,
+          0x2c39aab0,
+          0x2c3a2ac2,
+          0x2c3aaad6,
+          0x2c3b2ae7,
+          0x2c3bab06,
+          0x2c3c2b1a,
+          0x2c3cab30,
+          0x2c3d2b49,
+          0x2c3dab66,
+          0x2c3e2b77,
+          0x2c3eab85,
+          0x2c3f2b9d,
+          0x2c3fabb5,
+          0x2c402bc2,
           0x2c4090e7,
-          0x2c412aec,
-          0x2c41aaff,
+          0x2c412bd3,
+          0x2c41abe6,
           0x2c4210c0,
-          0x2c42ab10,
+          0x2c42abf7,
           0x2c430720,
-          0x2c43aa11,
+          0x2c43aaf8,
           0x30320000,
           0x30328015,
           0x3033001f,
@@ -577,180 +573,189 @@
           0x403b9861,
           0x403c0064,
           0x403c8083,
-          0x403d18aa,
-          0x403d98c0,
-          0x403e18cf,
-          0x403e98e2,
-          0x403f18fc,
-          0x403f990a,
-          0x4040191f,
-          0x40409933,
-          0x40411950,
-          0x4041996b,
-          0x40421984,
-          0x40429997,
-          0x404319ab,
-          0x404399c3,
-          0x404419da,
+          0x403d18c1,
+          0x403d98d7,
+          0x403e18e6,
+          0x403e98f9,
+          0x403f1913,
+          0x403f9921,
+          0x40401936,
+          0x4040994a,
+          0x40411967,
+          0x40419982,
+          0x4042199b,
+          0x404299ae,
+          0x404319c2,
+          0x404399da,
+          0x404419f1,
           0x404480ac,
-          0x404519ef,
-          0x40459a01,
-          0x40461a25,
-          0x40469a45,
-          0x40471a53,
-          0x40479a7a,
-          0x40481ab7,
-          0x40489ad0,
-          0x40491ae7,
-          0x40499b01,
-          0x404a1b18,
-          0x404a9b36,
-          0x404b1b4e,
-          0x404b9b65,
-          0x404c1b7b,
-          0x404c9b8d,
-          0x404d1bae,
-          0x404d9bd0,
-          0x404e1be4,
-          0x404e9bf1,
-          0x404f1c1e,
-          0x404f9c47,
-          0x40501c71,
-          0x40509c85,
-          0x40511ca0,
-          0x40519cb0,
-          0x40521cc7,
-          0x40529ceb,
-          0x40531d03,
-          0x40539d16,
-          0x40541d2b,
-          0x40549d4e,
-          0x40551d5c,
-          0x40559d79,
-          0x40561d86,
-          0x40569d9f,
-          0x40571db7,
-          0x40579dca,
-          0x40581ddf,
-          0x40589e06,
-          0x40591e35,
-          0x40599e62,
-          0x405a1e76,
-          0x405a9e86,
-          0x405b1e9e,
-          0x405b9eaf,
-          0x405c1ec2,
-          0x405c9ed3,
-          0x405d1ee0,
-          0x405d9ef7,
-          0x405e1f17,
+          0x40451a06,
+          0x40459a18,
+          0x40461a3c,
+          0x40469a5c,
+          0x40471a6a,
+          0x40479a91,
+          0x40481ace,
+          0x40489ae7,
+          0x40491afe,
+          0x40499b18,
+          0x404a1b2f,
+          0x404a9b4d,
+          0x404b1b65,
+          0x404b9b7c,
+          0x404c1b92,
+          0x404c9ba4,
+          0x404d1bc5,
+          0x404d9be7,
+          0x404e1bfb,
+          0x404e9c08,
+          0x404f1c35,
+          0x404f9c5e,
+          0x40501c99,
+          0x40509cad,
+          0x40511cc8,
+          0x40519cd8,
+          0x40521cef,
+          0x40529d13,
+          0x40531d2b,
+          0x40539d3e,
+          0x40541d53,
+          0x40549d76,
+          0x40551d84,
+          0x40559da1,
+          0x40561dae,
+          0x40569dc7,
+          0x40571ddf,
+          0x40579df2,
+          0x40581e07,
+          0x40589e2e,
+          0x40591e5d,
+          0x40599e8a,
+          0x405a1e9e,
+          0x405a9eae,
+          0x405b1ec6,
+          0x405b9ed7,
+          0x405c1eea,
+          0x405c9f0b,
+          0x405d1f18,
+          0x405d9f2f,
+          0x405e1f6d,
           0x405e8a95,
-          0x405f1f38,
-          0x405f9f45,
-          0x40601f53,
-          0x40609f75,
-          0x40611f9d,
-          0x40619fb2,
-          0x40621fc9,
-          0x40629fda,
-          0x40631feb,
-          0x4063a000,
-          0x40642017,
-          0x4064a043,
-          0x4065205e,
-          0x4065a075,
-          0x4066208d,
-          0x4066a0b7,
-          0x406720e2,
-          0x4067a103,
-          0x40682116,
-          0x4068a137,
-          0x40692169,
-          0x4069a197,
-          0x406a21b8,
-          0x406aa1d8,
-          0x406b2360,
-          0x406ba383,
-          0x406c2399,
-          0x406ca5c5,
-          0x406d25f4,
-          0x406da61c,
-          0x406e264a,
-          0x406ea662,
-          0x406f2681,
-          0x406fa696,
-          0x407026a9,
-          0x4070a6c6,
+          0x405f1f8e,
+          0x405f9f9b,
+          0x40601fa9,
+          0x40609fcb,
+          0x4061200f,
+          0x4061a047,
+          0x4062205e,
+          0x4062a06f,
+          0x40632080,
+          0x4063a095,
+          0x406420ac,
+          0x4064a0d8,
+          0x406520f3,
+          0x4065a10a,
+          0x40662122,
+          0x4066a14c,
+          0x40672177,
+          0x4067a198,
+          0x406821ab,
+          0x4068a1cc,
+          0x406921fe,
+          0x4069a22c,
+          0x406a224d,
+          0x406aa26d,
+          0x406b23f5,
+          0x406ba418,
+          0x406c242e,
+          0x406ca690,
+          0x406d26bf,
+          0x406da6e7,
+          0x406e2715,
+          0x406ea749,
+          0x406f2768,
+          0x406fa77d,
+          0x40702790,
+          0x4070a7ad,
           0x40710800,
-          0x4071a6d8,
-          0x407226eb,
-          0x4072a704,
-          0x4073271c,
+          0x4071a7bf,
+          0x407227d2,
+          0x4072a7eb,
+          0x40732803,
           0x4073936d,
-          0x40742730,
-          0x4074a74a,
-          0x4075275b,
-          0x4075a76f,
-          0x4076277d,
+          0x40742817,
+          0x4074a831,
+          0x40752842,
+          0x4075a856,
+          0x40762864,
           0x407691aa,
-          0x407727a2,
-          0x4077a7c4,
-          0x407827df,
-          0x4078a818,
-          0x4079282f,
-          0x4079a845,
-          0x407a2851,
-          0x407aa864,
-          0x407b2879,
-          0x407ba88b,
-          0x407c28a0,
-          0x407ca8a9,
-          0x407d2152,
-          0x407d9c57,
-          0x407e27f4,
-          0x407e9e16,
-          0x407f1a67,
+          0x40772889,
+          0x4077a8ab,
+          0x407828c6,
+          0x4078a8ff,
+          0x40792916,
+          0x4079a92c,
+          0x407a2938,
+          0x407aa94b,
+          0x407b2960,
+          0x407ba972,
+          0x407c2987,
+          0x407ca990,
+          0x407d21e7,
+          0x407d9c6e,
+          0x407e28db,
+          0x407e9e3e,
+          0x407f1a7e,
           0x407f9887,
-          0x40801c2e,
-          0x40809a8f,
-          0x40811cd9,
-          0x40819c08,
-          0x40822635,
+          0x40801c45,
+          0x40809aa6,
+          0x40811d01,
+          0x40819c1f,
+          0x40822700,
           0x4082986d,
-          0x40831df1,
-          0x4083a028,
-          0x40841aa3,
-          0x40849e4e,
-          0x41f4228b,
-          0x41f9231d,
-          0x41fe2210,
-          0x41fea3ec,
-          0x41ff24dd,
-          0x420322a4,
-          0x420822c6,
-          0x4208a302,
-          0x420921f4,
-          0x4209a33c,
-          0x420a224b,
-          0x420aa22b,
-          0x420b226b,
-          0x420ba2e4,
-          0x420c24f9,
-          0x420ca3b9,
-          0x420d23d3,
-          0x420da40a,
-          0x42122424,
-          0x421724c0,
-          0x4217a466,
-          0x421c2488,
-          0x421f2443,
-          0x42212510,
-          0x422624a3,
-          0x422b25a9,
-          0x422ba572,
-          0x422c2591,
-          0x422ca54c,
-          0x422d252b,
+          0x40831e19,
+          0x4083a0bd,
+          0x40841aba,
+          0x40849e76,
+          0x40851efb,
+          0x40859ff3,
+          0x40861f4f,
+          0x40869c88,
+          0x4087272d,
+          0x4087a024,
+          0x408818aa,
+          0x41f42320,
+          0x41f923b2,
+          0x41fe22a5,
+          0x41fea481,
+          0x41ff2572,
+          0x42032339,
+          0x4208235b,
+          0x4208a397,
+          0x42092289,
+          0x4209a3d1,
+          0x420a22e0,
+          0x420aa2c0,
+          0x420b2300,
+          0x420ba379,
+          0x420c258e,
+          0x420ca44e,
+          0x420d2468,
+          0x420da49f,
+          0x421224b9,
+          0x42172555,
+          0x4217a4fb,
+          0x421c251d,
+          0x421f24d8,
+          0x422125a5,
+          0x42262538,
+          0x422b2674,
+          0x422ba622,
+          0x422c265c,
+          0x422ca5e1,
+          0x422d25c0,
+          0x422da641,
+          0x422e2607,
           0x4432072b,
           0x4432873a,
           0x44330746,
@@ -793,69 +798,69 @@
           0x4c3d136d,
           0x4c3d937c,
           0x4c3e1389,
-          0x50322b22,
-          0x5032ab31,
-          0x50332b3c,
-          0x5033ab4c,
-          0x50342b65,
-          0x5034ab7f,
-          0x50352b8d,
-          0x5035aba3,
-          0x50362bb5,
-          0x5036abcb,
-          0x50372be4,
-          0x5037abf7,
-          0x50382c0f,
-          0x5038ac20,
-          0x50392c35,
-          0x5039ac49,
-          0x503a2c69,
-          0x503aac7f,
-          0x503b2c97,
-          0x503baca9,
-          0x503c2cc5,
-          0x503cacdc,
-          0x503d2cf5,
-          0x503dad0b,
-          0x503e2d18,
-          0x503ead2e,
-          0x503f2d40,
+          0x50322c09,
+          0x5032ac18,
+          0x50332c23,
+          0x5033ac33,
+          0x50342c4c,
+          0x5034ac66,
+          0x50352c74,
+          0x5035ac8a,
+          0x50362c9c,
+          0x5036acb2,
+          0x50372ccb,
+          0x5037acde,
+          0x50382cf6,
+          0x5038ad07,
+          0x50392d1c,
+          0x5039ad30,
+          0x503a2d50,
+          0x503aad66,
+          0x503b2d7e,
+          0x503bad90,
+          0x503c2dac,
+          0x503cadc3,
+          0x503d2ddc,
+          0x503dadf2,
+          0x503e2dff,
+          0x503eae15,
+          0x503f2e27,
           0x503f8382,
-          0x50402d53,
-          0x5040ad63,
-          0x50412d7d,
-          0x5041ad8c,
-          0x50422da6,
-          0x5042adc3,
-          0x50432dd3,
-          0x5043ade3,
-          0x50442df2,
+          0x50402e3a,
+          0x5040ae4a,
+          0x50412e64,
+          0x5041ae73,
+          0x50422e8d,
+          0x5042aeaa,
+          0x50432eba,
+          0x5043aeca,
+          0x50442ed9,
           0x5044843f,
-          0x50452e06,
-          0x5045ae24,
-          0x50462e37,
-          0x5046ae4d,
-          0x50472e5f,
-          0x5047ae74,
-          0x50482e9a,
-          0x5048aea8,
-          0x50492ebb,
-          0x5049aed0,
-          0x504a2ee6,
-          0x504aaef6,
-          0x504b2f16,
-          0x504baf29,
-          0x504c2f4c,
-          0x504caf7a,
-          0x504d2f8c,
-          0x504dafa9,
-          0x504e2fc4,
-          0x504eafe0,
-          0x504f2ff2,
-          0x504fb009,
-          0x50503018,
+          0x50452eed,
+          0x5045af0b,
+          0x50462f1e,
+          0x5046af34,
+          0x50472f46,
+          0x5047af5b,
+          0x50482f81,
+          0x5048af8f,
+          0x50492fa2,
+          0x5049afb7,
+          0x504a2fcd,
+          0x504aafdd,
+          0x504b2ffd,
+          0x504bb010,
+          0x504c3033,
+          0x504cb061,
+          0x504d3073,
+          0x504db090,
+          0x504e30ab,
+          0x504eb0c7,
+          0x504f30d9,
+          0x504fb0f0,
+          0x505030ff,
           0x505086ef,
-          0x5051302b,
+          0x50513112,
           0x58320ec9,
           0x68320e8b,
           0x68328c25,
@@ -1218,6 +1223,7 @@
           "BIO_NOT_SET\\0"
           "BLOCK_CIPHER_PAD_IS_WRONG\\0"
           "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0"
+          "CANNOT_PARSE_LEAF_CERT\\0"
           "CA_DN_LENGTH_MISMATCH\\0"
           "CA_DN_TOO_LONG\\0"
           "CCS_RECEIVED_EARLY\\0"
@@ -1261,6 +1267,7 @@
           "INVALID_COMPRESSION_LIST\\0"
           "INVALID_MESSAGE\\0"
           "INVALID_OUTER_RECORD_TYPE\\0"
+          "INVALID_SCT_LIST\\0"
           "INVALID_SSL_SESSION\\0"
           "INVALID_TICKET_KEYS_LENGTH\\0"
           "LENGTH_MISMATCH\\0"
@@ -1290,15 +1297,19 @@
           "NO_RENEGOTIATION\\0"
           "NO_REQUIRED_DIGEST\\0"
           "NO_SHARED_CIPHER\\0"
+          "NO_SHARED_GROUP\\0"
           "NULL_SSL_CTX\\0"
           "NULL_SSL_METHOD_PASSED\\0"
           "OLD_SESSION_CIPHER_NOT_RETURNED\\0"
+          "OLD_SESSION_PRF_HASH_MISMATCH\\0"
           "OLD_SESSION_VERSION_NOT_RETURNED\\0"
           "PARSE_TLSEXT\\0"
           "PATH_TOO_LONG\\0"
           "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0"
           "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0"
+          "PRE_SHARED_KEY_MUST_BE_LAST\\0"
           "PROTOCOL_IS_SHUTDOWN\\0"
+          "PSK_IDENTITY_BINDER_COUNT_MISMATCH\\0"
           "PSK_IDENTITY_NOT_FOUND\\0"
           "PSK_NO_CLIENT_CB\\0"
           "PSK_NO_SERVER_CB\\0"
@@ -1350,7 +1361,9 @@
           "TLSV1_ALERT_USER_CANCELLED\\0"
           "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0"
           "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0"
+          "TLSV1_CERTIFICATE_REQUIRED\\0"
           "TLSV1_CERTIFICATE_UNOBTAINABLE\\0"
+          "TLSV1_UNKNOWN_PSK_IDENTITY\\0"
           "TLSV1_UNRECOGNIZED_NAME\\0"
           "TLSV1_UNSUPPORTED_EXTENSION\\0"
           "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0"
@@ -1358,6 +1371,7 @@
           "TOO_MANY_EMPTY_FRAGMENTS\\0"
           "TOO_MANY_KEY_UPDATES\\0"
           "TOO_MANY_WARNING_ALERTS\\0"
+          "TOO_MUCH_SKIPPED_EARLY_DATA\\0"
           "UNABLE_TO_FIND_ECDH_PARAMETERS\\0"
           "UNEXPECTED_EXTENSION\\0"
           "UNEXPECTED_MESSAGE\\0"
diff --git a/src/objective-c/GRPCClient/private/NSData+GRPC.m b/src/objective-c/GRPCClient/private/NSData+GRPC.m
index 7ee76ad..7c46594 100644
--- a/src/objective-c/GRPCClient/private/NSData+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSData+GRPC.m
@@ -47,6 +47,8 @@
   grpc_slice_unref(slice);
   *array = result;
   *length = uncompressed_length;
+
+  grpc_byte_buffer_reader_destroy(&reader);
 }
 
 static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array,
diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.m b/src/objective-c/RxLibrary/GRXBufferedPipe.m
index 99cb0ad..577a5e9 100644
--- a/src/objective-c/RxLibrary/GRXBufferedPipe.m
+++ b/src/objective-c/RxLibrary/GRXBufferedPipe.m
@@ -110,4 +110,12 @@
   self.state = GRXWriterStateFinished;
 }
 
+- (void)dealloc {
+  GRXWriterState state = self.state;
+  if (state == GRXWriterStateNotStarted ||
+      state == GRXWriterStatePaused) {
+    dispatch_resume(_writeQueue);
+  }
+}
+
 @end
diff --git a/src/objective-c/tests/RxLibraryUnitTests.m b/src/objective-c/tests/RxLibraryUnitTests.m
index fa3ded4..3a5adbb 100644
--- a/src/objective-c/tests/RxLibraryUnitTests.m
+++ b/src/objective-c/tests/RxLibraryUnitTests.m
@@ -213,4 +213,74 @@
   XCTAssertEqualObjects(handler.errorOrNil, nil);
 }
 
+#define WRITE_ROUNDS (1000)
+- (void)testBufferedPipeResumeWhenDealloc {
+  id anyValue = @7;
+  id<GRXWriteable> writeable = [GRXWriteable  writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
+  }];
+
+  // Release after alloc;
+  GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
+  pipe = nil;
+
+  // Release after write but before start
+  pipe = [GRXBufferedPipe pipe];
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  pipe = nil;
+
+  // Release after start but not write
+  pipe = [GRXBufferedPipe pipe];
+  [pipe startWithWriteable:writeable];
+  pipe = nil;
+
+  // Release after start and write
+  pipe = [GRXBufferedPipe pipe];
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  [pipe startWithWriteable:writeable];
+  pipe = nil;
+
+  // Release after start, write and pause
+  pipe = [GRXBufferedPipe pipe];
+  [pipe startWithWriteable:writeable];
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  pipe.state = GRXWriterStatePaused;
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  pipe = nil;
+
+  // Release after start, write, pause and finish
+  pipe = [GRXBufferedPipe pipe];
+  [pipe startWithWriteable:writeable];
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  pipe.state = GRXWriterStatePaused;
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  [pipe finishWithError:nil];
+  pipe = nil;
+
+  // Release after start, write, pause, finish and resume
+  pipe = [GRXBufferedPipe pipe];
+  [pipe startWithWriteable:writeable];
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  pipe.state = GRXWriterStatePaused;
+  for (int i = 0; i < WRITE_ROUNDS; i++) {
+    [pipe writeValue:anyValue];
+  }
+  [pipe finishWithError:nil];
+  pipe.state = GRXWriterStateStarted;
+  pipe = nil;
+}
+
 @end
diff --git a/src/objective-c/tests/build_one_example.sh b/src/objective-c/tests/build_one_example.sh
index 5762760..298d8e7 100755
--- a/src/objective-c/tests/build_one_example.sh
+++ b/src/objective-c/tests/build_one_example.sh
@@ -37,9 +37,11 @@
 pod install
 
 set -o pipefail
-XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)'
+XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail|\bpassed\b)'
 xcodebuild \
     build \
     -workspace *.xcworkspace \
     -scheme $SCHEME \
-    -destination name="iPhone 6" | xcpretty
+    -destination name="iPhone 6" \
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 8fa9439..d9c78eb 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -70,7 +70,7 @@
 # element of the pipe fails.
 # TODO(jcanizales): Use xctool instead? Issue #2540.
 set -o pipefail
-XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)'
+XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail|\bpassed\b)'
 echo "TIME:  $(date)"
 xcodebuild \
     -workspace Tests.xcworkspace \
@@ -79,14 +79,18 @@
     HOST_PORT_LOCALSSL=localhost:5051 \
     HOST_PORT_LOCAL=localhost:5050 \
     HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
-    test | xcpretty
+    test \
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
 
 echo "TIME:  $(date)"
 xcodebuild \
     -workspace Tests.xcworkspace \
     -scheme CoreCronetEnd2EndTests \
     -destination name="iPhone 6" \
-    test | xcpretty
+    test \
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
 
 # Temporarily disabled for (possible) flakiness on Jenkins.
 # Fix or reenable after confirmation/disconfirmation that it is the source of
@@ -105,4 +109,6 @@
     -scheme InteropTestsRemoteWithCronet \
     -destination name="iPhone 6" \
     HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
-    test | xcpretty
+    test \
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/src/proto/grpc/health/v1/BUILD b/src/proto/grpc/health/v1/BUILD
index db04f37..6f67795 100644
--- a/src/proto/grpc/health/v1/BUILD
+++ b/src/proto/grpc/health/v1/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
diff --git a/src/proto/grpc/lb/v1/BUILD b/src/proto/grpc/lb/v1/BUILD
index 7fbfdfe..61b28ee 100644
--- a/src/proto/grpc/lb/v1/BUILD
+++ b/src/proto/grpc/lb/v1/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
diff --git a/src/proto/grpc/lb/v1/load_balancer.proto b/src/proto/grpc/lb/v1/load_balancer.proto
index b13b343..0a33568 100644
--- a/src/proto/grpc/lb/v1/load_balancer.proto
+++ b/src/proto/grpc/lb/v1/load_balancer.proto
@@ -67,6 +67,15 @@
   string name = 1;
 }
 
+// Contains the number of calls finished for a particular load balance token.
+message ClientStatsPerToken {
+  // See Server.load_balance_token.
+  string load_balance_token = 1;
+
+  // The total number of RPCs that finished associated with the token.
+  int64 num_calls = 2;
+}
+
 // Contains client level statistics that are useful to load balancing. Each
 // count except the timestamp should be reset to zero after reporting the stats.
 message ClientStats {
@@ -79,20 +88,17 @@
   // The total number of RPCs that finished.
   int64 num_calls_finished = 3;
 
-  // The total number of RPCs that were dropped by the client because of rate
-  // limiting.
-  int64 num_calls_finished_with_drop_for_rate_limiting = 4;
-
-  // The total number of RPCs that were dropped by the client because of load
-  // balancing.
-  int64 num_calls_finished_with_drop_for_load_balancing = 5;
-
   // The total number of RPCs that failed to reach a server except dropped RPCs.
   int64 num_calls_finished_with_client_failed_to_send = 6;
 
   // The total number of RPCs that finished and are known to have been received
   // by a server.
   int64 num_calls_finished_known_received = 7;
+
+  // The list of dropped calls.
+  repeated ClientStatsPerToken calls_finished_with_drop = 8;
+
+  reserved 4, 5;
 }
 
 message LoadBalanceResponse {
@@ -134,10 +140,8 @@
   Duration expiration_interval = 3;
 }
 
-// Contains server information. When none of the [drop_for_*] fields are true,
-// use the other fields. When drop_for_rate_limiting is true, ignore all other
-// fields. Use drop_for_load_balancing only when it is true and
-// drop_for_rate_limiting is false.
+// Contains server information. When the drop field is not true, use the other
+// fields.
 message Server {
   // A resolved address for the server, serialized in network-byte-order. It may
   // either be an IPv4 or IPv6 address.
@@ -149,16 +153,16 @@
   // An opaque but printable token given to the frontend for each pick. All
   // frontend requests for that pick must include the token in its initial
   // metadata. The token is used by the backend to verify the request and to
-  // allow the backend to report load to the gRPC LB system.
+  // allow the backend to report load to the gRPC LB system. The token is also
+  // used in client stats for reporting dropped calls.
   //
   // Its length is variable but less than 50 bytes.
   string load_balance_token = 3;
 
-  // Indicates whether this particular request should be dropped by the client
-  // for rate limiting.
-  bool drop_for_rate_limiting = 4;
+  // Indicates whether this particular request should be dropped by the client.
+  // If the request is dropped, there will be a corresponding entry in
+  // ClientStats.calls_finished_with_drop.
+  bool drop = 4;
 
-  // Indicates whether this particular request should be dropped by the client
-  // for load balancing.
-  bool drop_for_load_balancing = 5;
+  reserved 5;
 }
diff --git a/src/proto/grpc/reflection/v1alpha/BUILD b/src/proto/grpc/reflection/v1alpha/BUILD
index 0d9df4f..b60784e 100644
--- a/src/proto/grpc/reflection/v1alpha/BUILD
+++ b/src/proto/grpc/reflection/v1alpha/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
diff --git a/src/proto/grpc/status/BUILD b/src/proto/grpc/status/BUILD
index 10c162d..61688e5 100644
--- a/src/proto/grpc/status/BUILD
+++ b/src/proto/grpc/status/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
@@ -22,5 +28,5 @@
     name = "status_proto",
     srcs = ["status.proto"],
     has_services = False,
-    well_known_protos = "@com_google_protobuf//:well_known_protos",
+    well_known_protos = True,
 )
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index 0c27297..c8e7d03 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto
index 4801664..2ff2e4e 100644
--- a/src/proto/grpc/testing/control.proto
+++ b/src/proto/grpc/testing/control.proto
@@ -64,6 +64,7 @@
 message SecurityParams {
   bool use_test_ca = 1;
   string server_host_override = 2;
+  string cred_type = 3;
 }
 
 message ChannelArg {
@@ -240,6 +241,10 @@
   // Number of polls called inside completion queue per request
   double client_polls_per_request = 15;
   double server_polls_per_request = 16;
+
+  // Queries per CPU-sec over all servers or clients
+  double server_queries_per_cpu_sec = 17;
+  double client_queries_per_cpu_sec = 18;
 }
 
 // Results of a single benchmark scenario.
diff --git a/src/proto/grpc/testing/duplicate/BUILD b/src/proto/grpc/testing/duplicate/BUILD
index dd715d8..8f91710 100644
--- a/src/proto/grpc/testing/duplicate/BUILD
+++ b/src/proto/grpc/testing/duplicate/BUILD
@@ -14,7 +14,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
index 929aaa1..7decae9 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
@@ -34,7 +34,7 @@
 def peer_identities(Call call):
   cdef grpc_auth_context* auth_context
   cdef grpc_auth_property_iterator properties
-  cdef grpc_auth_property* property
+  cdef const grpc_auth_property* property
 
   auth_context = grpc_call_auth_context(call.c_call)
   if auth_context == NULL:
@@ -52,7 +52,7 @@
 
 def peer_identity_key(Call call):
   cdef grpc_auth_context* auth_context
-  cdef char* c_key
+  cdef const char* c_key
   auth_context = grpc_call_auth_context(call.c_call)
   if auth_context == NULL:
     return None
@@ -67,7 +67,7 @@
 def auth_context(Call call):
   cdef grpc_auth_context* auth_context
   cdef grpc_auth_property_iterator properties
-  cdef grpc_auth_property* property
+  cdef const grpc_auth_property* property
 
   auth_context = grpc_call_auth_context(call.c_call)
   if auth_context == NULL:
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index ea5bdba..aa074df 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -71,6 +71,7 @@
   'src/core/lib/channel/handshaker_registry.c',
   'src/core/lib/compression/compression.c',
   'src/core/lib/compression/message_compress.c',
+  'src/core/lib/compression/stream_compression.c',
   'src/core/lib/http/format_request.c',
   'src/core/lib/http/httpcli.c',
   'src/core/lib/http/parser.c',
@@ -192,6 +193,7 @@
   'src/core/ext/transport/chttp2/transport/bin_encoder.c',
   'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
   'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
+  'src/core/ext/transport/chttp2/transport/flow_control.c',
   'src/core/ext/transport/chttp2/transport/frame_data.c',
   'src/core/ext/transport/chttp2/transport/frame_goaway.c',
   'src/core/ext/transport/chttp2/transport/frame_ping.c',
@@ -239,6 +241,7 @@
   'src/core/lib/security/util/json_util.c',
   'src/core/lib/surface/init_secure.c',
   'src/core/tsi/fake_transport_security.c',
+  'src/core/tsi/gts_transport_security.c',
   'src/core/tsi/ssl_transport_security.c',
   'src/core/tsi/transport_security.c',
   'src/core/tsi/transport_security_adapter.c',
@@ -270,6 +273,8 @@
   'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c',
   'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
   'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
+  'src/core/ext/transport/inproc/inproc_plugin.c',
+  'src/core/ext/transport/inproc/inproc_transport.c',
   'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c',
   'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c',
   'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c',
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 83e0ead..0299b4c 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -24,6 +24,18 @@
 import health_commands
 import grpc_version
 
+CLASSIFIERS = [
+    'Development Status :: 5 - Production/Stable',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.4',
+    'Programming Language :: Python :: 3.5',
+    'Programming Language :: Python :: 3.6',
+    'License :: OSI Approved :: Apache Software License',
+],
+
 PACKAGE_DIRECTORIES = {
     '': '.',
 }
@@ -48,6 +60,7 @@
     author_email='grpc-io@googlegroups.com',
     url='https://grpc.io',
     license='Apache License 2.0',
+    classifiers=CLASSIFIERS,
     package_dir=PACKAGE_DIRECTORIES,
     packages=setuptools.find_packages('.'),
     install_requires=INSTALL_REQUIRES,
diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py
index 20edbc4..bed2311 100644
--- a/src/python/grpcio_reflection/setup.py
+++ b/src/python/grpcio_reflection/setup.py
@@ -25,6 +25,18 @@
 import reflection_commands
 import grpc_version
 
+CLASSIFIERS = [
+    'Development Status :: 5 - Production/Stable',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.4',
+    'Programming Language :: Python :: 3.5',
+    'Programming Language :: Python :: 3.6',
+    'License :: OSI Approved :: Apache Software License',
+],
+
 PACKAGE_DIRECTORIES = {
     '': '.',
 }
@@ -48,6 +60,7 @@
     description='Standard Protobuf Reflection Service for gRPC',
     author='The gRPC Authors',
     author_email='grpc-io@googlegroups.com',
+    classifiers=CLASSIFIERS,
     url='https://grpc.io',
     package_dir=PACKAGE_DIRECTORIES,
     packages=setuptools.find_packages('.'),
diff --git a/src/python/grpcio_testing/grpc_testing/__init__.py b/src/python/grpcio_testing/grpc_testing/__init__.py
new file mode 100644
index 0000000..c5a17f4
--- /dev/null
+++ b/src/python/grpcio_testing/grpc_testing/__init__.py
@@ -0,0 +1,119 @@
+# 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.
+"""Objects for use in testing gRPC Python-using application code."""
+
+import abc
+
+import six
+
+import grpc
+
+
+class Time(six.with_metaclass(abc.ABCMeta)):
+    """A simulation of time.
+
+    Implementations needn't be connected with real time as provided by the
+    Python interpreter, but as long as systems under test use
+    RpcContext.is_active and RpcContext.time_remaining for querying RPC liveness
+    implementations may be used to change passage of time in tests.
+    """
+
+    @abc.abstractmethod
+    def time(self):
+        """Accesses the current test time.
+
+        Returns:
+          The current test time (over which this object has authority).
+        """
+        raise NotImplementedError()
+
+    @abc.abstractmethod
+    def call_in(self, behavior, delay):
+        """Adds a behavior to be called after some time.
+
+        Args:
+          behavior: A behavior to be called with no arguments.
+          delay: A duration of time in seconds after which to call the behavior.
+
+        Returns:
+          A grpc.Future with which the call of the behavior may be cancelled
+            before it is executed.
+        """
+        raise NotImplementedError()
+
+    @abc.abstractmethod
+    def call_at(self, behavior, time):
+        """Adds a behavior to be called at a specific time.
+
+        Args:
+          behavior: A behavior to be called with no arguments.
+          time: The test time at which to call the behavior.
+
+        Returns:
+          A grpc.Future with which the call of the behavior may be cancelled
+            before it is executed.
+        """
+        raise NotImplementedError()
+
+    @abc.abstractmethod
+    def sleep_for(self, duration):
+        """Blocks for some length of test time.
+
+        Args:
+          duration: A duration of test time in seconds for which to block.
+        """
+        raise NotImplementedError()
+
+    @abc.abstractmethod
+    def sleep_until(self, time):
+        """Blocks until some test time.
+
+        Args:
+          time: The test time until which to block.
+        """
+        raise NotImplementedError()
+
+
+def strict_real_time():
+    """Creates a Time backed by the Python interpreter's time.
+
+    The returned instance will be "strict" with respect to callbacks
+    submitted to it: it will ensure that all callbacks registered to
+    be called at time t have been called before it describes the time
+    as having advanced beyond t.
+
+    Returns:
+      A Time backed by the "system" (Python interpreter's) time.
+    """
+    from grpc_testing import _time
+    return _time.StrictRealTime()
+
+
+def strict_fake_time(now):
+    """Creates a Time that can be manipulated by test code.
+
+    The returned instance maintains an internal representation of time
+    independent of real time. This internal representation only advances
+    when user code calls the instance's sleep_for and sleep_until methods.
+
+    The returned instance will be "strict" with respect to callbacks
+    submitted to it: it will ensure that all callbacks registered to
+    be called at time t have been called before it describes the time
+    as having advanced beyond t.
+
+    Returns:
+      A Time that simulates the passage of time.
+    """
+    from grpc_testing import _time
+    return _time.StrictFakeTime(now)
diff --git a/src/python/grpcio_testing/grpc_testing/_time.py b/src/python/grpcio_testing/grpc_testing/_time.py
new file mode 100644
index 0000000..3b1ab4b
--- /dev/null
+++ b/src/python/grpcio_testing/grpc_testing/_time.py
@@ -0,0 +1,224 @@
+# 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.
+"""Test times."""
+
+import collections
+import logging
+import threading
+import time as _time
+
+import grpc
+import grpc_testing
+
+
+def _call(behaviors):
+    for behavior in behaviors:
+        try:
+            behavior()
+        except Exception:  # pylint: disable=broad-except
+            logging.exception('Exception calling behavior "%r"!', behavior)
+
+
+def _call_in_thread(behaviors):
+    calling = threading.Thread(target=_call, args=(behaviors,))
+    calling.start()
+    # NOTE(nathaniel): Because this function is called from "strict" Time
+    # implementations, it blocks until after all behaviors have terminated.
+    calling.join()
+
+
+class _State(object):
+
+    def __init__(self):
+        self.condition = threading.Condition()
+        self.times_to_behaviors = collections.defaultdict(list)
+
+
+class _Delta(
+        collections.namedtuple('_Delta',
+                               ('mature_behaviors', 'earliest_mature_time',
+                                'earliest_immature_time',))):
+    pass
+
+
+def _process(state, now):
+    mature_behaviors = []
+    earliest_mature_time = None
+    while state.times_to_behaviors:
+        earliest_time = min(state.times_to_behaviors)
+        if earliest_time <= now:
+            if earliest_mature_time is None:
+                earliest_mature_time = earliest_time
+            earliest_mature_behaviors = state.times_to_behaviors.pop(
+                earliest_time)
+            mature_behaviors.extend(earliest_mature_behaviors)
+        else:
+            earliest_immature_time = earliest_time
+            break
+    else:
+        earliest_immature_time = None
+    return _Delta(mature_behaviors, earliest_mature_time,
+                  earliest_immature_time)
+
+
+class _Future(grpc.Future):
+
+    def __init__(self, state, behavior, time):
+        self._state = state
+        self._behavior = behavior
+        self._time = time
+        self._cancelled = False
+
+    def cancel(self):
+        with self._state.condition:
+            if self._cancelled:
+                return True
+            else:
+                behaviors_at_time = self._state.times_to_behaviors.get(
+                    self._time)
+                if behaviors_at_time is None:
+                    return False
+                else:
+                    behaviors_at_time.remove(self._behavior)
+                    if not behaviors_at_time:
+                        self._state.times_to_behaviors.pop(self._time)
+                        self._state.condition.notify_all()
+                    self._cancelled = True
+                    return True
+
+    def cancelled(self):
+        with self._state.condition:
+            return self._cancelled
+
+    def running(self):
+        raise NotImplementedError()
+
+    def done(self):
+        raise NotImplementedError()
+
+    def result(self, timeout=None):
+        raise NotImplementedError()
+
+    def exception(self, timeout=None):
+        raise NotImplementedError()
+
+    def traceback(self, timeout=None):
+        raise NotImplementedError()
+
+    def add_done_callback(self, fn):
+        raise NotImplementedError()
+
+
+class StrictRealTime(grpc_testing.Time):
+
+    def __init__(self):
+        self._state = _State()
+        self._active = False
+        self._calling = None
+
+    def _activity(self):
+        while True:
+            with self._state.condition:
+                while True:
+                    now = _time.time()
+                    delta = _process(self._state, now)
+                    self._state.condition.notify_all()
+                    if delta.mature_behaviors:
+                        self._calling = delta.earliest_mature_time
+                        break
+                    self._calling = None
+                    if delta.earliest_immature_time is None:
+                        self._active = False
+                        return
+                    else:
+                        timeout = max(0, delta.earliest_immature_time - now)
+                        self._state.condition.wait(timeout=timeout)
+            _call(delta.mature_behaviors)
+
+    def _ensure_called_through(self, time):
+        with self._state.condition:
+            while ((self._state.times_to_behaviors and
+                    min(self._state.times_to_behaviors) < time) or
+                   (self._calling is not None and self._calling < time)):
+                self._state.condition.wait()
+
+    def _call_at(self, behavior, time):
+        with self._state.condition:
+            self._state.times_to_behaviors[time].append(behavior)
+            if self._active:
+                self._state.condition.notify_all()
+            else:
+                activity = threading.Thread(target=self._activity)
+                activity.start()
+                self._active = True
+            return _Future(self._state, behavior, time)
+
+    def time(self):
+        return _time.time()
+
+    def call_in(self, behavior, delay):
+        return self._call_at(behavior, _time.time() + delay)
+
+    def call_at(self, behavior, time):
+        return self._call_at(behavior, time)
+
+    def sleep_for(self, duration):
+        time = _time.time() + duration
+        _time.sleep(duration)
+        self._ensure_called_through(time)
+
+    def sleep_until(self, time):
+        _time.sleep(max(0, time - _time.time()))
+        self._ensure_called_through(time)
+
+
+class StrictFakeTime(grpc_testing.Time):
+
+    def __init__(self, time):
+        self._state = _State()
+        self._time = time
+
+    def time(self):
+        return self._time
+
+    def call_in(self, behavior, delay):
+        if delay <= 0:
+            _call_in_thread((behavior,))
+        else:
+            with self._state.condition:
+                time = self._time + delay
+                self._state.times_to_behaviors[time].append(behavior)
+        return _Future(self._state, behavior, time)
+
+    def call_at(self, behavior, time):
+        with self._state.condition:
+            if time <= self._time:
+                _call_in_thread((behavior,))
+            else:
+                self._state.times_to_behaviors[time].append(behavior)
+        return _Future(self._state, behavior, time)
+
+    def sleep_for(self, duration):
+        if 0 < duration:
+            with self._state.condition:
+                self._time += duration
+                delta = _process(self._state, self._time)
+                _call_in_thread(delta.mature_behaviors)
+
+    def sleep_until(self, time):
+        with self._state.condition:
+            if self._time < time:
+                self._time = time
+                delta = _process(self._state, self._time)
+                _call_in_thread(delta.mature_behaviors)
diff --git a/tools/internal_ci/macos/grpc_master.cfg b/src/python/grpcio_testing/grpc_version.py
similarity index 68%
copy from tools/internal_ci/macos/grpc_master.cfg
copy to src/python/grpcio_testing/grpc_version.py
index 1c34979..41a75d4 100644
--- a/tools/internal_ci/macos/grpc_master.cfg
+++ b/src/python/grpcio_testing/grpc_version.py
@@ -12,13 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Config file for the internal CI (in protobuf text format)
+# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/macos/grpc_master.sh"
-timeout_mins: 240
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.xml"
-  }
-}
+VERSION = '1.5.0.dev0'
diff --git a/src/python/grpcio_testing/setup.py b/src/python/grpcio_testing/setup.py
new file mode 100644
index 0000000..0cc336a
--- /dev/null
+++ b/src/python/grpcio_testing/setup.py
@@ -0,0 +1,44 @@
+# 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.
+"""Setup module for gRPC Python's testing package."""
+
+import os
+import sys
+
+import setuptools
+
+# Ensure we're in the proper directory whether or not we're being used by pip.
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+# Break import style to ensure that we can find same-directory modules.
+import grpc_version
+
+PACKAGE_DIRECTORIES = {
+    '': '.',
+}
+
+INSTALL_REQUIRES = ('protobuf>=3.3.0',
+                    'grpcio>={version}'.format(version=grpc_version.VERSION),)
+
+setuptools.setup(
+    name='grpcio-testing',
+    version=grpc_version.VERSION,
+    license='Apache License 2.0',
+    description='Testing utilities for gRPC Python',
+    author='The gRPC Authors',
+    author_email='grpc-io@googlegroups.com',
+    url='https://grpc.io',
+    package_dir=PACKAGE_DIRECTORIES,
+    packages=setuptools.find_packages('.'),
+    install_requires=INSTALL_REQUIRES)
diff --git a/src/python/grpcio_tests/.gitignore b/src/python/grpcio_tests/.gitignore
index dcba283..4f00cd9 100644
--- a/src/python/grpcio_tests/.gitignore
+++ b/src/python/grpcio_tests/.gitignore
@@ -1,5 +1 @@
-proto/
-src/
-*_pb2.py
-*_pb2_grpc.py
-*.egg-info/
+/src/
diff --git a/tools/internal_ci/macos/grpc_master.cfg b/src/python/grpcio_tests/tests/testing/__init__.py
similarity index 68%
copy from tools/internal_ci/macos/grpc_master.cfg
copy to src/python/grpcio_tests/tests/testing/__init__.py
index 1c34979..1e12035 100644
--- a/tools/internal_ci/macos/grpc_master.cfg
+++ b/src/python/grpcio_tests/tests/testing/__init__.py
@@ -11,14 +11,3 @@
 # 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.
-
-# Config file for the internal CI (in protobuf text format)
-
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/macos/grpc_master.sh"
-timeout_mins: 240
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.xml"
-  }
-}
diff --git a/src/python/grpcio_tests/tests/testing/_time_test.py b/src/python/grpcio_tests/tests/testing/_time_test.py
new file mode 100644
index 0000000..797394a
--- /dev/null
+++ b/src/python/grpcio_tests/tests/testing/_time_test.py
@@ -0,0 +1,165 @@
+# 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.
+
+import random
+import threading
+import time
+import unittest
+
+import grpc_testing
+
+_QUANTUM = 0.3
+_MANY = 10000
+# Tests that run in real time can either wait for the scheduler to
+# eventually run what needs to be run (and risk timing out) or declare
+# that the scheduler didn't schedule work reasonably fast enough. We
+# choose the latter for this test.
+_PATHOLOGICAL_SCHEDULING = 'pathological thread scheduling!'
+
+
+class _TimeNoter(object):
+
+    def __init__(self, time):
+        self._condition = threading.Condition()
+        self._time = time
+        self._call_times = []
+
+    def __call__(self):
+        with self._condition:
+            self._call_times.append(self._time.time())
+
+    def call_times(self):
+        with self._condition:
+            return tuple(self._call_times)
+
+
+class TimeTest(object):
+
+    def test_sleep_for(self):
+        start_time = self._time.time()
+        self._time.sleep_for(_QUANTUM)
+        end_time = self._time.time()
+
+        self.assertLessEqual(start_time + _QUANTUM, end_time)
+
+    def test_sleep_until(self):
+        start_time = self._time.time()
+        self._time.sleep_until(start_time + _QUANTUM)
+        end_time = self._time.time()
+
+        self.assertLessEqual(start_time + _QUANTUM, end_time)
+
+    def test_call_in(self):
+        time_noter = _TimeNoter(self._time)
+
+        start_time = self._time.time()
+        self._time.call_in(time_noter, _QUANTUM)
+        self._time.sleep_for(_QUANTUM * 2)
+        call_times = time_noter.call_times()
+
+        self.assertTrue(call_times, msg=_PATHOLOGICAL_SCHEDULING)
+        self.assertLessEqual(start_time + _QUANTUM, call_times[0])
+
+    def test_call_at(self):
+        time_noter = _TimeNoter(self._time)
+
+        start_time = self._time.time()
+        self._time.call_at(time_noter, self._time.time() + _QUANTUM)
+        self._time.sleep_for(_QUANTUM * 2)
+        call_times = time_noter.call_times()
+
+        self.assertTrue(call_times, msg=_PATHOLOGICAL_SCHEDULING)
+        self.assertLessEqual(start_time + _QUANTUM, call_times[0])
+
+    def test_cancel(self):
+        time_noter = _TimeNoter(self._time)
+
+        future = self._time.call_in(time_noter, _QUANTUM * 2)
+        self._time.sleep_for(_QUANTUM)
+        cancelled = future.cancel()
+        self._time.sleep_for(_QUANTUM * 2)
+        call_times = time_noter.call_times()
+
+        self.assertFalse(call_times, msg=_PATHOLOGICAL_SCHEDULING)
+        self.assertTrue(cancelled)
+        self.assertTrue(future.cancelled())
+
+    def test_many(self):
+        test_events = tuple(threading.Event() for _ in range(_MANY))
+        possibly_cancelled_futures = {}
+        background_noise_futures = []
+
+        for test_event in test_events:
+            possibly_cancelled_futures[test_event] = self._time.call_in(
+                test_event.set, _QUANTUM * (2 + random.random()))
+        for _ in range(_MANY):
+            background_noise_futures.append(
+                self._time.call_in(threading.Event().set, _QUANTUM * 1000 *
+                                   random.random()))
+        self._time.sleep_for(_QUANTUM)
+        cancelled = set()
+        for test_event, test_future in possibly_cancelled_futures.items():
+            if bool(random.randint(0, 1)) and test_future.cancel():
+                cancelled.add(test_event)
+        self._time.sleep_for(_QUANTUM * 3)
+
+        for test_event in test_events:
+            (self.assertFalse if test_event in cancelled else
+             self.assertTrue)(test_event.is_set())
+        for background_noise_future in background_noise_futures:
+            background_noise_future.cancel()
+
+    def test_same_behavior_used_several_times(self):
+        time_noter = _TimeNoter(self._time)
+
+        start_time = self._time.time()
+        first_future_at_one = self._time.call_in(time_noter, _QUANTUM)
+        second_future_at_one = self._time.call_in(time_noter, _QUANTUM)
+        first_future_at_three = self._time.call_in(time_noter, _QUANTUM * 3)
+        second_future_at_three = self._time.call_in(time_noter, _QUANTUM * 3)
+        self._time.sleep_for(_QUANTUM * 2)
+        first_future_at_one_cancelled = first_future_at_one.cancel()
+        second_future_at_one_cancelled = second_future_at_one.cancel()
+        first_future_at_three_cancelled = first_future_at_three.cancel()
+        self._time.sleep_for(_QUANTUM * 2)
+        second_future_at_three_cancelled = second_future_at_three.cancel()
+        first_future_at_three_cancelled_again = first_future_at_three.cancel()
+        call_times = time_noter.call_times()
+
+        self.assertEqual(3, len(call_times), msg=_PATHOLOGICAL_SCHEDULING)
+        self.assertFalse(first_future_at_one_cancelled)
+        self.assertFalse(second_future_at_one_cancelled)
+        self.assertTrue(first_future_at_three_cancelled)
+        self.assertFalse(second_future_at_three_cancelled)
+        self.assertTrue(first_future_at_three_cancelled_again)
+        self.assertLessEqual(start_time + _QUANTUM, call_times[0])
+        self.assertLessEqual(start_time + _QUANTUM, call_times[1])
+        self.assertLessEqual(start_time + _QUANTUM * 3, call_times[2])
+
+
+class StrictRealTimeTest(TimeTest, unittest.TestCase):
+
+    def setUp(self):
+        self._time = grpc_testing.strict_real_time()
+
+
+class StrictFakeTimeTest(TimeTest, unittest.TestCase):
+
+    def setUp(self):
+        self._time = grpc_testing.strict_fake_time(
+            random.randint(0, int(time.time())))
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index 126e8ac..f86eeb7 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -9,6 +9,8 @@
   "protoc_plugin._split_definitions_test.SplitSeparateTest",
   "protoc_plugin.beta_python_plugin_test.PythonPluginTest",
   "reflection._reflection_servicer_test.ReflectionServicerTest",
+  "testing._time_test.StrictFakeTimeTest",
+  "testing._time_test.StrictRealTimeTest",
   "unit._api_test.AllTest",
   "unit._api_test.ChannelConnectivityTest",
   "unit._api_test.ChannelTest",
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 67425a6..b999548 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -24,6 +24,8 @@
 #include <grpc/grpc.h>
 #include <grpc/impl/codegen/compression_types.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 
 #include "rb_byte_buffer.h"
 #include "rb_call_credentials.h"
@@ -368,7 +370,7 @@
    to fill grpc_metadata_array.
 
    it's capacity should have been computed via a prior call to
-   grpc_rb_md_ary_fill_hash_cb
+   grpc_rb_md_ary_capacity_hash_cb
 */
 static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
   grpc_metadata_array *md_ary = NULL;
@@ -376,7 +378,7 @@
   long i;
   grpc_slice key_slice;
   grpc_slice value_slice;
-  char *tmp_str;
+  char *tmp_str = NULL;
 
   if (TYPE(key) == T_SYMBOL) {
     key_slice = grpc_slice_from_static_string(rb_id2name(SYM2ID(key)));
@@ -386,6 +388,7 @@
   } else {
     rb_raise(rb_eTypeError,
              "grpc_rb_md_ary_fill_hash_cb: bad type for key parameter");
+    return ST_STOP;
   }
 
   if (!grpc_header_key_is_legal(key_slice)) {
@@ -413,6 +416,7 @@
                  tmp_str);
         return ST_STOP;
       }
+      GPR_ASSERT(md_ary->count < md_ary->capacity);
       md_ary->metadata[md_ary->count].key = key_slice;
       md_ary->metadata[md_ary->count].value = value_slice;
       md_ary->count += 1;
@@ -428,6 +432,7 @@
                tmp_str);
       return ST_STOP;
     }
+    GPR_ASSERT(md_ary->count < md_ary->capacity);
     md_ary->metadata[md_ary->count].key = key_slice;
     md_ary->metadata[md_ary->count].value = value_slice;
     md_ary->count += 1;
@@ -435,7 +440,6 @@
     rb_raise(rb_eArgError, "Header values must be of type string or array");
     return ST_STOP;
   }
-
   return ST_CONTINUE;
 }
 
@@ -458,6 +462,7 @@
   } else {
     md_ary->capacity += 1;
   }
+
   return ST_CONTINUE;
 }
 
@@ -480,7 +485,7 @@
   md_ary_obj =
       TypedData_Wrap_Struct(grpc_rb_cMdAry, &grpc_rb_md_ary_data_type, md_ary);
   rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_capacity_hash_cb, md_ary_obj);
-  md_ary->metadata = gpr_malloc(md_ary->capacity * sizeof(grpc_metadata));
+  md_ary->metadata = gpr_zalloc(md_ary->capacity * sizeof(grpc_metadata));
   rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_fill_hash_cb, md_ary_obj);
 }
 
@@ -611,13 +616,25 @@
   st->write_flag = write_flag;
 }
 
+void grpc_rb_metadata_array_destroy_including_entries(
+    grpc_metadata_array *array) {
+  size_t i;
+  if (array->metadata) {
+    for (i = 0; i < array->count; i++) {
+      grpc_slice_unref(array->metadata[i].key);
+      grpc_slice_unref(array->metadata[i].value);
+    }
+  }
+  grpc_metadata_array_destroy(array);
+}
+
 /* grpc_run_batch_stack_cleanup ensures the run_batch_stack is properly
  * cleaned up */
 static void grpc_run_batch_stack_cleanup(run_batch_stack *st) {
   size_t i = 0;
 
-  grpc_metadata_array_destroy(&st->send_metadata);
-  grpc_metadata_array_destroy(&st->send_trailing_metadata);
+  grpc_rb_metadata_array_destroy_including_entries(&st->send_metadata);
+  grpc_rb_metadata_array_destroy_including_entries(&st->send_trailing_metadata);
   grpc_metadata_array_destroy(&st->recv_metadata);
   grpc_metadata_array_destroy(&st->recv_trailing_metadata);
 
@@ -658,8 +675,6 @@
     st->ops[st->op_num].flags = 0;
     switch (NUM2INT(this_op)) {
       case GRPC_OP_SEND_INITIAL_METADATA:
-        /* N.B. later there is no need to explicitly delete the metadata keys
-         * and values, they are references to data in ruby objects. */
         grpc_rb_md_ary_convert(this_value, &st->send_metadata);
         st->ops[st->op_num].data.send_initial_metadata.count =
             st->send_metadata.count;
@@ -675,8 +690,6 @@
       case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
         break;
       case GRPC_OP_SEND_STATUS_FROM_SERVER:
-        /* N.B. later there is no need to explicitly delete the metadata keys
-         * and values, they are references to data in ruby objects. */
         grpc_rb_op_update_status_from_server(
             &st->ops[st->op_num], &st->send_trailing_metadata,
             &st->send_status_details, this_value);
diff --git a/src/ruby/ext/grpc/rb_call.h b/src/ruby/ext/grpc/rb_call.h
index be791cf..bfe8035 100644
--- a/src/ruby/ext/grpc/rb_call.h
+++ b/src/ruby/ext/grpc/rb_call.h
@@ -40,6 +40,9 @@
 */
 void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ary);
 
+void grpc_rb_metadata_array_destroy_including_entries(
+    grpc_metadata_array *md_ary);
+
 /* grpc_rb_eCallError is the ruby class of the exception thrown during call
    operations. */
 extern VALUE grpc_rb_eCallError;
diff --git a/src/ruby/ext/grpc/rb_call_credentials.c b/src/ruby/ext/grpc/rb_call_credentials.c
index 95e01a2..049a869 100644
--- a/src/ruby/ext/grpc/rb_call_credentials.c
+++ b/src/ruby/ext/grpc/rb_call_credentials.c
@@ -108,7 +108,7 @@
   error_details = StringValueCStr(details);
   params->callback(params->user_data, md_ary.metadata, md_ary.count, status,
                    error_details);
-  grpc_metadata_array_destroy(&md_ary);
+  grpc_rb_metadata_array_destroy_including_entries(&md_ary);
   gpr_free(params);
 }
 
@@ -239,6 +239,7 @@
                                               VALUE self) {
   grpc_call_credentials *creds;
   grpc_call_credentials *other;
+  grpc_call_credentials *prev = NULL;
   VALUE mark;
   if (argc == 0) {
     return self;
@@ -249,6 +250,10 @@
     rb_ary_push(mark, argv[i]);
     other = grpc_rb_get_wrapped_call_credentials(argv[i]);
     creds = grpc_composite_call_credentials_create(creds, other, NULL);
+    if (prev != NULL) {
+      grpc_call_credentials_release(prev);
+    }
+    prev = creds;
   }
   return grpc_rb_wrap_call_credentials(creds, mark);
 }
diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
index 07935a1..83601ca 100644
--- a/src/ruby/ext/grpc/rb_channel_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -184,6 +184,7 @@
                                                  VALUE self) {
   grpc_channel_credentials *creds;
   grpc_call_credentials *other;
+  grpc_channel_credentials *prev = NULL;
   VALUE mark;
   if (argc == 0) {
     return self;
@@ -195,6 +196,11 @@
     rb_ary_push(mark, argv[i]);
     other = grpc_rb_get_wrapped_call_credentials(argv[i]);
     creds = grpc_composite_channel_credentials_create(creds, other, NULL);
+    if (prev != NULL) {
+      grpc_channel_credentials_release(prev);
+    }
+    prev = creds;
+
     if (creds == NULL) {
       rb_raise(rb_eRuntimeError,
                "Failed to compose channel and call credentials");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index a477ab6..5288704 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -644,22 +644,22 @@
 typedef gpr_avl(*gpr_avl_create_type)(const gpr_avl_vtable *vtable);
 extern gpr_avl_create_type gpr_avl_create_import;
 #define gpr_avl_create gpr_avl_create_import
-typedef gpr_avl(*gpr_avl_ref_type)(gpr_avl avl);
+typedef gpr_avl(*gpr_avl_ref_type)(gpr_avl avl, void *user_data);
 extern gpr_avl_ref_type gpr_avl_ref_import;
 #define gpr_avl_ref gpr_avl_ref_import
-typedef void(*gpr_avl_unref_type)(gpr_avl avl);
+typedef void(*gpr_avl_unref_type)(gpr_avl avl, void *user_data);
 extern gpr_avl_unref_type gpr_avl_unref_import;
 #define gpr_avl_unref gpr_avl_unref_import
-typedef gpr_avl(*gpr_avl_add_type)(gpr_avl avl, void *key, void *value);
+typedef gpr_avl(*gpr_avl_add_type)(gpr_avl avl, void *key, void *value, void *user_data);
 extern gpr_avl_add_type gpr_avl_add_import;
 #define gpr_avl_add gpr_avl_add_import
-typedef gpr_avl(*gpr_avl_remove_type)(gpr_avl avl, void *key);
+typedef gpr_avl(*gpr_avl_remove_type)(gpr_avl avl, void *key, void *user_data);
 extern gpr_avl_remove_type gpr_avl_remove_import;
 #define gpr_avl_remove gpr_avl_remove_import
-typedef void *(*gpr_avl_get_type)(gpr_avl avl, void *key);
+typedef void *(*gpr_avl_get_type)(gpr_avl avl, void *key, void *user_data);
 extern gpr_avl_get_type gpr_avl_get_import;
 #define gpr_avl_get gpr_avl_get_import
-typedef int(*gpr_avl_maybe_get_type)(gpr_avl avl, void *key, void **value);
+typedef int(*gpr_avl_maybe_get_type)(gpr_avl avl, void *key, void **value, void *user_data);
 extern gpr_avl_maybe_get_type gpr_avl_maybe_get_import;
 #define gpr_avl_maybe_get gpr_avl_maybe_get_import
 typedef int(*gpr_avl_is_empty_type)(gpr_avl avl);
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index cb407d2..10eb70b 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -40,13 +40,13 @@
 module GRPC
   # The ActiveCall class provides simple methods for sending marshallable
   # data to a call
-  class ActiveCall
+  class ActiveCall # rubocop:disable Metrics/ClassLength
     include Core::TimeConsts
     include Core::CallOps
     extend Forwardable
-    attr_reader :deadline, :metadata_sent, :metadata_to_send
+    attr_reader :deadline, :metadata_sent, :metadata_to_send, :peer, :peer_cert
     def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=,
-                   :peer, :peer_cert, :trailing_metadata
+                   :trailing_metadata, :status
 
     # client_invoke begins a client invocation.
     #
@@ -100,6 +100,18 @@
       fail(ArgumentError, 'Already sent md') if started && metadata_to_send
       @metadata_to_send = metadata_to_send || {} unless started
       @send_initial_md_mutex = Mutex.new
+
+      @output_stream_done = false
+      @input_stream_done = false
+      @call_finished = false
+      @call_finished_mu = Mutex.new
+
+      @client_call_executed = false
+      @client_call_executed_mu = Mutex.new
+
+      # set the peer now so that the accessor can still function
+      # after the server closes the call
+      @peer = call.peer
     end
 
     # Sends the initial metadata that has yet to be sent.
@@ -142,11 +154,9 @@
       Operation.new(self)
     end
 
-    # finished waits until a client call is completed.
-    #
-    # It blocks until the remote endpoint acknowledges by sending a status.
-    def finished
+    def receive_and_check_status
       batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
+      set_input_stream_done
       attach_status_results_and_complete_call(batch_result)
     end
 
@@ -155,8 +165,6 @@
         @call.trailing_metadata = recv_status_batch_result.status.metadata
       end
       @call.status = recv_status_batch_result.status
-      @call.close
-      op_is_done
 
       # The RECV_STATUS in run_batch always succeeds
       # Check the status for a bad status or failed run batch
@@ -193,9 +201,19 @@
       }
       ops[RECV_CLOSE_ON_SERVER] = nil if assert_finished
       @call.run_batch(ops)
+      set_output_stream_done
+
       nil
     end
 
+    # Intended for use on server-side calls when a single request from
+    # the client is expected (i.e., unary and server-streaming RPC types).
+    def read_unary_request
+      req = remote_read
+      set_input_stream_done
+      req
+    end
+
     def server_unary_response(req, trailing_metadata: {},
                               code: Core::StatusCodes::OK, details: 'OK')
       ops = {}
@@ -211,6 +229,7 @@
       ops[RECV_CLOSE_ON_SERVER] = nil
 
       @call.run_batch(ops)
+      set_output_stream_done
     end
 
     # remote_read reads a response from the remote endpoint.
@@ -241,6 +260,8 @@
 
     # each_remote_read passes each response to the given block or returns an
     # enumerator the responses if no block is given.
+    # Used to generate the request enumerable for
+    # server-side client-streaming RPC's.
     #
     # == Enumerator ==
     #
@@ -258,10 +279,14 @@
     # @return [Enumerator] if no block was given
     def each_remote_read
       return enum_for(:each_remote_read) unless block_given?
-      loop do
-        resp = remote_read
-        break if resp.nil?  # the last response was received
-        yield resp
+      begin
+        loop do
+          resp = remote_read
+          break if resp.nil?  # the last response was received
+          yield resp
+        end
+      ensure
+        set_input_stream_done
       end
     end
 
@@ -287,13 +312,17 @@
     # @return [Enumerator] if no block was given
     def each_remote_read_then_finish
       return enum_for(:each_remote_read_then_finish) unless block_given?
-      loop do
-        resp = remote_read
-        if resp.nil?  # the last response was received, but not finished yet
-          finished
-          break
+      begin
+        loop do
+          resp = remote_read
+          if resp.nil?  # the last response was received
+            receive_and_check_status
+            break
+          end
+          yield resp
         end
-        yield resp
+      ensure
+        set_input_stream_done
       end
     end
 
@@ -305,6 +334,7 @@
     # a list, multiple metadata for its key are sent
     # @return [Object] the response received from the server
     def request_response(req, metadata: {})
+      raise_error_if_already_executed
       ops = {
         SEND_MESSAGE => @marshal.call(req),
         SEND_CLOSE_FROM_CLIENT => nil,
@@ -319,7 +349,15 @@
         end
         @metadata_sent = true
       end
-      batch_result = @call.run_batch(ops)
+
+      begin
+        batch_result = @call.run_batch(ops)
+        # no need to check for cancellation after a CallError because this
+        # batch contains a RECV_STATUS op
+      ensure
+        set_input_stream_done
+        set_output_stream_done
+      end
 
       @call.metadata = batch_result.metadata
       attach_status_results_and_complete_call(batch_result)
@@ -339,10 +377,20 @@
     # a list, multiple metadata for its key are sent
     # @return [Object] the response received from the server
     def client_streamer(requests, metadata: {})
-      # Metadata might have already been sent if this is an operation view
-      merge_metadata_and_send_if_not_already_sent(metadata)
+      raise_error_if_already_executed
+      begin
+        merge_metadata_and_send_if_not_already_sent(metadata)
+        requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
+      rescue GRPC::Core::CallError => e
+        receive_and_check_status # check for Cancelled
+        raise e
+      rescue => e
+        set_input_stream_done
+        raise e
+      ensure
+        set_output_stream_done
+      end
 
-      requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
       batch_result = @call.run_batch(
         SEND_CLOSE_FROM_CLIENT => nil,
         RECV_INITIAL_METADATA => nil,
@@ -350,12 +398,11 @@
         RECV_STATUS_ON_CLIENT => nil
       )
 
+      set_input_stream_done
+
       @call.metadata = batch_result.metadata
       attach_status_results_and_complete_call(batch_result)
       get_message_from_batch_result(batch_result)
-    rescue GRPC::Core::CallError => e
-      finished  # checks for Cancelled
-      raise e
     end
 
     # server_streamer sends one request to the GRPC server, which yields a
@@ -373,6 +420,7 @@
     # a list, multiple metadata for its key are sent
     # @return [Enumerator|nil] a response Enumerator
     def server_streamer(req, metadata: {})
+      raise_error_if_already_executed
       ops = {
         SEND_MESSAGE => @marshal.call(req),
         SEND_CLOSE_FROM_CLIENT => nil
@@ -384,13 +432,22 @@
         end
         @metadata_sent = true
       end
-      @call.run_batch(ops)
+
+      begin
+        @call.run_batch(ops)
+      rescue GRPC::Core::CallError => e
+        receive_and_check_status # checks for Cancelled
+        raise e
+      rescue => e
+        set_input_stream_done
+        raise e
+      ensure
+        set_output_stream_done
+      end
+
       replies = enum_for(:each_remote_read_then_finish)
       return replies unless block_given?
       replies.each { |r| yield r }
-    rescue GRPC::Core::CallError => e
-      finished  # checks for Cancelled
-      raise e
     end
 
     # bidi_streamer sends a stream of requests to the GRPC server, and yields
@@ -421,14 +478,31 @@
     # a list, multiple metadata for its key are sent
     # @return [Enumerator, nil] a response Enumerator
     def bidi_streamer(requests, metadata: {}, &blk)
+      raise_error_if_already_executed
       # Metadata might have already been sent if this is an operation view
-      merge_metadata_and_send_if_not_already_sent(metadata)
+      begin
+        merge_metadata_and_send_if_not_already_sent(metadata)
+      rescue GRPC::Core::CallError => e
+        batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
+        set_input_stream_done
+        set_output_stream_done
+        attach_status_results_and_complete_call(batch_result)
+        raise e
+      rescue => e
+        set_input_stream_done
+        set_output_stream_done
+        raise e
+      end
+
       bd = BidiCall.new(@call,
                         @marshal,
                         @unmarshal,
                         metadata_received: @metadata_received)
 
-      bd.run_on_client(requests, @op_notifier, &blk)
+      bd.run_on_client(requests,
+                       proc { set_input_stream_done },
+                       proc { set_output_stream_done },
+                       &blk)
     end
 
     # run_server_bidi orchestrates a BiDi stream processing on a server.
@@ -449,7 +523,7 @@
                         metadata_received: @metadata_received,
                         req_view: MultiReqView.new(self))
 
-      bd.run_on_server(gen_each_reply)
+      bd.run_on_server(gen_each_reply, proc { set_input_stream_done })
     end
 
     # Waits till an operation completes
@@ -459,7 +533,8 @@
       @op_notifier.wait
     end
 
-    # Signals that an operation is done
+    # Signals that an operation is done.
+    # Only relevant on the client-side (this is a no-op on the server-side)
     def op_is_done
       return if @op_notifier.nil?
       @op_notifier.notify(self)
@@ -484,8 +559,40 @@
       end
     end
 
+    def attach_peer_cert(peer_cert)
+      @peer_cert = peer_cert
+    end
+
     private
 
+    # To be called once the "input stream" has been completelly
+    # read through (i.e, done reading from client or received status)
+    # note this is idempotent
+    def set_input_stream_done
+      @call_finished_mu.synchronize do
+        @input_stream_done = true
+        maybe_finish_and_close_call_locked
+      end
+    end
+
+    # To be called once the "output stream" has been completelly
+    # sent through (i.e, done sending from client or sent status)
+    # note this is idempotent
+    def set_output_stream_done
+      @call_finished_mu.synchronize do
+        @output_stream_done = true
+        maybe_finish_and_close_call_locked
+      end
+    end
+
+    def maybe_finish_and_close_call_locked
+      return unless @output_stream_done && @input_stream_done
+      return if @call_finished
+      @call_finished = true
+      op_is_done
+      @call.close
+    end
+
     # Starts the call if not already started
     # @param metadata [Hash] metadata to be sent to the server. If a value is
     # a list, multiple metadata for its key are sent
@@ -493,6 +600,15 @@
       merge_metadata_to_send(metadata) && send_initial_metadata
     end
 
+    def raise_error_if_already_executed
+      @client_call_executed_mu.synchronize do
+        if @client_call_executed
+          fail GRPC::Core::CallError, 'attempting to re-run a call'
+        end
+        @client_call_executed = true
+      end
+    end
+
     def self.view_class(*visible_methods)
       Class.new do
         extend ::Forwardable
@@ -516,8 +632,9 @@
 
     # MultiReqView limits access to an ActiveCall's methods for use in
     # server client_streamer handlers.
-    MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg,
+    MultiReqView = view_class(:cancelled?, :deadline,
                               :each_remote_read, :metadata, :output_metadata,
+                              :peer, :peer_cert,
                               :send_initial_metadata,
                               :metadata_to_send,
                               :merge_metadata_to_send,
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index e54cf78..9e125cd 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -62,12 +62,19 @@
     # block that can be invoked with each response.
     #
     # @param requests the Enumerable of requests to send
-    # @param op_notifier a Notifier used to signal completion
+    # @param set_input_stream_done [Proc] called back when we're done
+    #   reading the input stream
+    # @param set_input_stream_done [Proc] called back when we're done
+    #   sending data on the output stream
     # @return an Enumerator of requests to yield
-    def run_on_client(requests, op_notifier, &blk)
-      @op_notifier = op_notifier
-      @enq_th = Thread.new { write_loop(requests) }
-      read_loop(&blk)
+    def run_on_client(requests,
+                      set_input_stream_done,
+                      set_output_stream_done,
+                      &blk)
+      @enq_th = Thread.new do
+        write_loop(requests, set_output_stream_done: set_output_stream_done)
+      end
+      read_loop(set_input_stream_done, &blk)
     end
 
     # Begins orchestration of the Bidi stream for a server generating replies.
@@ -81,12 +88,17 @@
     # produced by gen_each_reply could ignore the received_msgs
     #
     # @param gen_each_reply [Proc] generates the BiDi stream replies.
-    def run_on_server(gen_each_reply)
+    # @param set_input_steam_done [Proc] call back to call when
+    #   the reads have been completely read through.
+    def run_on_server(gen_each_reply, set_input_stream_done)
       # Pass in the optional call object parameter if possible
       if gen_each_reply.arity == 1
-        replys = gen_each_reply.call(read_loop(is_client: false))
+        replys = gen_each_reply.call(
+          read_loop(set_input_stream_done, is_client: false))
       elsif gen_each_reply.arity == 2
-        replys = gen_each_reply.call(read_loop(is_client: false), @req_view)
+        replys = gen_each_reply.call(
+          read_loop(set_input_stream_done, is_client: false),
+          @req_view)
       else
         fail 'Illegal arity of reply generator'
       end
@@ -99,22 +111,6 @@
     END_OF_READS = :end_of_reads
     END_OF_WRITES = :end_of_writes
 
-    # signals that bidi operation is complete
-    def notify_done
-      return unless @op_notifier
-      GRPC.logger.debug("bidi-notify-done: notifying  #{@op_notifier}")
-      @op_notifier.notify(self)
-    end
-
-    # signals that a bidi operation is complete (read + write)
-    def finished
-      @done_mutex.synchronize do
-        return unless @reads_complete && @writes_complete && !@complete
-        @call.close
-        @complete = true
-      end
-    end
-
     # performs a read using @call.run_batch, ensures metadata is set up
     def read_using_run_batch
       ops = { RECV_MESSAGE => nil }
@@ -127,7 +123,8 @@
       batch_result
     end
 
-    def write_loop(requests, is_client: true)
+    # set_output_stream_done is relevant on client-side
+    def write_loop(requests, is_client: true, set_output_stream_done: nil)
       GRPC.logger.debug('bidi-write-loop: starting')
       count = 0
       requests.each do |req|
@@ -151,23 +148,20 @@
         GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
         @call.run_batch(SEND_CLOSE_FROM_CLIENT => nil)
         GRPC.logger.debug('bidi-write-loop: done')
-        notify_done
-        @writes_complete = true
-        finished
       end
       GRPC.logger.debug('bidi-write-loop: finished')
     rescue StandardError => e
       GRPC.logger.warn('bidi-write-loop: failed')
       GRPC.logger.warn(e)
-      notify_done
-      @writes_complete = true
-      finished
       raise e
+    ensure
+      set_output_stream_done.call if is_client
     end
 
     # Provides an enumerator that yields results of remote reads
-    def read_loop(is_client: true)
+    def read_loop(set_input_stream_done, is_client: true)
       return enum_for(:read_loop,
+                      set_input_stream_done,
                       is_client: is_client) unless block_given?
       GRPC.logger.debug('bidi-read-loop: starting')
       begin
@@ -201,10 +195,10 @@
         GRPC.logger.warn('bidi: read-loop failed')
         GRPC.logger.warn(e)
         raise e
+      ensure
+        set_input_stream_done.call
       end
       GRPC.logger.debug('bidi-read-loop: finished')
-      @reads_complete = true
-      finished
       # Make sure that the write loop is done done before finishing the call.
       # Note that blocking is ok at this point because we've already received
       # a status
diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb
index ce00975..89cf8ff 100644
--- a/src/ruby/lib/grpc/generic/rpc_desc.rb
+++ b/src/ruby/lib/grpc/generic/rpc_desc.rb
@@ -48,7 +48,7 @@
     end
 
     def handle_request_response(active_call, mth)
-      req = active_call.remote_read
+      req = active_call.read_unary_request
       resp = mth.call(req, active_call.single_req_view)
       active_call.server_unary_response(
         resp, trailing_metadata: active_call.output_metadata)
@@ -61,7 +61,7 @@
     end
 
     def handle_server_streamer(active_call, mth)
-      req = active_call.remote_read
+      req = active_call.read_unary_request
       replys = mth.call(req, active_call.single_req_view)
       replys.each { |r| active_call.remote_send(r) }
       send_status(active_call, OK, 'OK', active_call.output_metadata)
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index ef2cc0c..33b3cea 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -418,6 +418,7 @@
                          metadata_received: true,
                          started: false,
                          metadata_to_send: connect_md)
+      c.attach_peer_cert(an_rpc.call.peer_cert)
       mth = an_rpc.method.to_sym
       [c, mth]
     end
diff --git a/src/ruby/spec/client_auth_spec.rb b/src/ruby/spec/client_auth_spec.rb
new file mode 100644
index 0000000..79c9192
--- /dev/null
+++ b/src/ruby/spec/client_auth_spec.rb
@@ -0,0 +1,137 @@
+# 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.
+
+require 'grpc'
+
+def create_channel_creds
+  test_root = File.join(File.dirname(__FILE__), 'testdata')
+  files = ['ca.pem', 'client.key', 'client.pem']
+  creds = files.map { |f| File.open(File.join(test_root, f)).read }
+  GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
+end
+
+def client_cert
+  test_root = File.join(File.dirname(__FILE__), 'testdata')
+  cert = File.open(File.join(test_root, 'client.pem')).read
+  fail unless cert.is_a?(String)
+  cert
+end
+
+def create_server_creds
+  test_root = File.join(File.dirname(__FILE__), 'testdata')
+  p "test root: #{test_root}"
+  files = ['ca.pem', 'server1.key', 'server1.pem']
+  creds = files.map { |f| File.open(File.join(test_root, f)).read }
+  GRPC::Core::ServerCredentials.new(
+    creds[0],
+    [{ private_key: creds[1], cert_chain: creds[2] }],
+    true) # force client auth
+end
+
+# A test message
+class EchoMsg
+  def self.marshal(_o)
+    ''
+  end
+
+  def self.unmarshal(_o)
+    EchoMsg.new
+  end
+end
+
+# a test service that checks the cert of its peer
+class SslTestService
+  include GRPC::GenericService
+  rpc :an_rpc, EchoMsg, EchoMsg
+  rpc :a_client_streaming_rpc, stream(EchoMsg), EchoMsg
+  rpc :a_server_streaming_rpc, EchoMsg, stream(EchoMsg)
+  rpc :a_bidi_rpc, stream(EchoMsg), stream(EchoMsg)
+
+  def check_peer_cert(call)
+    error_msg = "want:\n#{client_cert}\n\ngot:\n#{call.peer_cert}"
+    fail(error_msg) unless call.peer_cert == client_cert
+  end
+
+  def an_rpc(req, call)
+    check_peer_cert(call)
+    req
+  end
+
+  def a_client_streaming_rpc(call)
+    check_peer_cert(call)
+    call.each_remote_read.each { |r| p r }
+    EchoMsg.new
+  end
+
+  def a_server_streaming_rpc(_, call)
+    check_peer_cert(call)
+    [EchoMsg.new, EchoMsg.new]
+  end
+
+  def a_bidi_rpc(requests, call)
+    check_peer_cert(call)
+    requests.each { |r| p r }
+    [EchoMsg.new, EchoMsg.new]
+  end
+end
+
+SslTestServiceStub = SslTestService.rpc_stub_class
+
+describe 'client-server auth' do
+  RpcServer = GRPC::RpcServer
+
+  before(:all) do
+    server_opts = {
+      poll_period: 1
+    }
+    @srv = RpcServer.new(**server_opts)
+    port = @srv.add_http2_port('0.0.0.0:0', create_server_creds)
+    @srv.handle(SslTestService)
+    @srv_thd = Thread.new { @srv.run }
+    @srv.wait_till_running
+
+    client_opts = {
+      channel_args: {
+        GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr'
+      }
+    }
+    @stub = SslTestServiceStub.new("localhost:#{port}",
+                                   create_channel_creds,
+                                   **client_opts)
+  end
+
+  after(:all) do
+    expect(@srv.stopped?).to be(false)
+    @srv.stop
+    @srv_thd.join
+  end
+
+  it 'client-server auth with unary RPCs' do
+    @stub.an_rpc(EchoMsg.new)
+  end
+
+  it 'client-server auth with client streaming RPCs' do
+    @stub.a_client_streaming_rpc([EchoMsg.new, EchoMsg.new])
+  end
+
+  it 'client-server auth with server streaming RPCs' do
+    responses = @stub.a_server_streaming_rpc(EchoMsg.new)
+    responses.each { |r| p r }
+  end
+
+  it 'client-server auth with bidi RPCs' do
+    responses = @stub.a_bidi_rpc([EchoMsg.new, EchoMsg.new])
+    responses.each { |r| p r }
+  end
+end
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index af3752c..b48b417 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -448,11 +448,18 @@
   it_behaves_like 'GRPC metadata delivery works OK' do
   end
 
-  it 'modifies metadata with CallCredentials' do
-    auth_proc = proc { { 'k1' => 'updated-v1' } }
+  def credentials_update_test(creds_update_md)
+    auth_proc = proc { creds_update_md }
     call_creds = GRPC::Core::CallCredentials.new(auth_proc)
-    md = { 'k2' => 'v2' }
-    expected_md = { 'k1' => 'updated-v1', 'k2' => 'v2' }
+
+    initial_md_key = 'k2'
+    initial_md_val = 'v2'
+    initial_md = {}
+    initial_md[initial_md_key] = initial_md_val
+    expected_md = creds_update_md.clone
+    fail 'bad test param' unless expected_md[initial_md_key].nil?
+    expected_md[initial_md_key] = initial_md_val
+
     recvd_rpc = nil
     rcv_thread = Thread.new do
       recvd_rpc = @server.request_call
@@ -461,7 +468,7 @@
     call = new_client_call
     call.set_credentials! call_creds
     client_ops = {
-      CallOps::SEND_INITIAL_METADATA => md
+      CallOps::SEND_INITIAL_METADATA => initial_md
     }
     batch_result = call.run_batch(client_ops)
     expect(batch_result.send_metadata).to be true
@@ -473,4 +480,21 @@
     replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
     expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
   end
+
+  it 'modifies metadata with CallCredentials' do
+    credentials_update_test('k1' => 'updated-v1')
+  end
+
+  it 'modifies large metadata with CallCredentials' do
+    val_array = %w(
+      '00000000000000000000000000000000000000000000000000000000000000',
+      '11111111111111111111111111111111111111111111111111111111111111',
+    )
+    md = {
+      k3: val_array,
+      k4: '0000000000000000000000000000000000000000000000000000000000',
+      keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey5: 'v1'
+    }
+    credentials_update_test(md)
+  end
 end
diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb
index 72e55eb..ec0c294 100644
--- a/src/ruby/spec/generic/active_call_spec.rb
+++ b/src/ruby/spec/generic/active_call_spec.rb
@@ -473,7 +473,7 @@
       server_call.remote_send('server_response')
       expect(client_call.remote_read).to eq('server_response')
       server_call.send_status(OK, 'status code is OK')
-      expect { client_call.finished }.to_not raise_error
+      expect { client_call.receive_and_check_status }.to_not raise_error
     end
 
     it 'finishes ok if the server sends an early status response' do
@@ -490,7 +490,7 @@
       expect do
         call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
       end.to_not raise_error
-      expect { client_call.finished }.to_not raise_error
+      expect { client_call.receive_and_check_status }.to_not raise_error
     end
 
     it 'finishes ok if SEND_CLOSE and RECV_STATUS has been sent' do
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index 09b88c7..e1e7a53 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -36,6 +36,53 @@
 include GRPC::Core::TimeConsts
 include GRPC::Core::CallOps
 
+# check that methods on a finished/closed call t crash
+def check_op_view_of_finished_client_call(op_view,
+                                          expected_metadata,
+                                          expected_trailing_metadata)
+  # use read_response_stream to try to iterate through
+  # possible response stream
+  fail('need something to attempt reads') unless block_given?
+  expect do
+    resp = op_view.execute
+    yield resp
+  end.to raise_error(GRPC::Core::CallError)
+
+  expect { op_view.start_call }.to raise_error(RuntimeError)
+
+  sanity_check_values_of_accessors(op_view,
+                                   expected_metadata,
+                                   expected_trailing_metadata)
+
+  expect do
+    op_view.wait
+    op_view.cancel
+    op_view.write_flag = 1
+  end.to_not raise_error
+end
+
+def sanity_check_values_of_accessors(op_view,
+                                     expected_metadata,
+                                     expected_trailing_metadata)
+  expected_status = Struct::Status.new
+  expected_status.code = 0
+  expected_status.details = 'OK'
+  expected_status.metadata = expected_trailing_metadata
+
+  expect(op_view.status).to eq(expected_status)
+  expect(op_view.metadata).to eq(expected_metadata)
+  expect(op_view.trailing_metadata).to eq(expected_trailing_metadata)
+
+  expect(op_view.cancelled?).to be(false)
+  expect(op_view.write_flag).to be(nil)
+
+  # The deadline attribute of a call can be either
+  # a GRPC::Core::TimeSpec or a Time, which are mutually exclusive.
+  # TODO: fix so that the accessor always returns the same type.
+  expect(op_view.deadline.is_a?(GRPC::Core::TimeSpec) ||
+         op_view.deadline.is_a?(Time)).to be(true)
+end
+
 describe 'ClientStub' do
   let(:noop) { proc { |x| x } }
 
@@ -45,6 +92,7 @@
     @method = 'an_rpc_method'
     @pass = OK
     @fail = INTERNAL
+    @metadata = { k1: 'v1', k2: 'v2' }
   end
 
   after(:each) do
@@ -107,7 +155,7 @@
     end
   end
 
-  describe '#request_response' do
+  describe '#request_response', request_response: true do
     before(:each) do
       @sent_msg, @resp = 'a_msg', 'a_reply'
     end
@@ -122,16 +170,42 @@
         th.join
       end
 
-      it 'should send metadata to the server ok' do
+      def metadata_test(md)
         server_port = create_test_server
         host = "localhost:#{server_port}"
         th = run_request_response(@sent_msg, @resp, @pass,
-                                  k1: 'v1', k2: 'v2')
+                                  expected_metadata: md)
         stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
+        @metadata = md
         expect(get_response(stub)).to eq(@resp)
         th.join
       end
 
+      it 'should send metadata to the server ok' do
+        metadata_test(k1: 'v1', k2: 'v2')
+      end
+
+      # these tests mostly try to exercise when md might be allocated
+      # instead of inlined
+      it 'should send metadata with multiple large md to the server ok' do
+        val_array = %w(
+          '00000000000000000000000000000000000000000000000000000000000000',
+          '11111111111111111111111111111111111111111111111111111111111111',
+          '22222222222222222222222222222222222222222222222222222222222222',
+        )
+        md = {
+          k1: val_array,
+          k2: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+          k3: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
+          k4: 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
+          keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey5: 'v5',
+          'k66666666666666666666666666666666666666666666666666666' => 'v6',
+          'k77777777777777777777777777777777777777777777777777777' => 'v7',
+          'k88888888888888888888888888888888888888888888888888888' => 'v8'
+        }
+        metadata_test(md)
+      end
+
       it 'should send a request when configured using an override channel' do
         server_port = create_test_server
         alt_host = "localhost:#{server_port}"
@@ -187,13 +261,24 @@
         # Kill the server thread so tests can complete
         th.kill
       end
+
+      it 'should raise ArgumentError if metadata contains invalid values' do
+        @metadata.merge!(k3: 3)
+        server_port = create_test_server
+        host = "localhost:#{server_port}"
+        stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
+        expect do
+          get_response(stub)
+        end.to raise_error(ArgumentError,
+                           /Header values must be of type string or array/)
+      end
     end
 
     describe 'without a call operation' do
       def get_response(stub, credentials: nil)
         puts credentials.inspect
         stub.request_response(@method, @sent_msg, noop, noop,
-                              metadata: { k1: 'v1', k2: 'v2' },
+                              metadata: @metadata,
                               credentials: credentials)
       end
 
@@ -201,40 +286,62 @@
     end
 
     describe 'via a call operation' do
+      after(:each) do
+        # make sure op.wait doesn't hang, even if there's a bad status
+        @op.wait
+      end
       def get_response(stub, run_start_call_first: false, credentials: nil)
-        op = stub.request_response(@method, @sent_msg, noop, noop,
-                                   return_op: true,
-                                   metadata: { k1: 'v1', k2: 'v2' },
-                                   deadline: from_relative_time(2),
-                                   credentials: credentials)
-        expect(op).to be_a(GRPC::ActiveCall::Operation)
-        op.start_call if run_start_call_first
-        result = op.execute
-        op.wait # make sure wait doesn't hang
+        @op = stub.request_response(@method, @sent_msg, noop, noop,
+                                    return_op: true,
+                                    metadata: @metadata,
+                                    deadline: from_relative_time(2),
+                                    credentials: credentials)
+        expect(@op).to be_a(GRPC::ActiveCall::Operation)
+        @op.start_call if run_start_call_first
+        result = @op.execute
         result
       end
 
       it_behaves_like 'request response'
 
-      it 'sends metadata to the server ok when running start_call first' do
+      def run_op_view_metadata_test(run_start_call_first)
         server_port = create_test_server
         host = "localhost:#{server_port}"
-        th = run_request_response(@sent_msg, @resp, @pass,
-                                  k1: 'v1', k2: 'v2')
+
+        @server_initial_md = { 'sk1' => 'sv1', 'sk2' => 'sv2' }
+        @server_trailing_md = { 'tk1' => 'tv1', 'tk2' => 'tv2' }
+        th = run_request_response(
+          @sent_msg, @resp, @pass,
+          expected_metadata: @metadata,
+          server_initial_md: @server_initial_md,
+          server_trailing_md: @server_trailing_md)
         stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
-        expect(get_response(stub)).to eq(@resp)
+        expect(
+          get_response(stub,
+                       run_start_call_first: run_start_call_first)).to eq(@resp)
         th.join
       end
+
+      it 'sends metadata to the server ok when running start_call first' do
+        run_op_view_metadata_test(true)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) { |r| p r }
+      end
+
+      it 'does not crash when used after the call has been finished' do
+        run_op_view_metadata_test(false)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) { |r| p r }
+      end
     end
   end
 
-  describe '#client_streamer' do
+  describe '#client_streamer', client_streamer: true do
     before(:each) do
       Thread.abort_on_exception = true
       server_port = create_test_server
       host = "localhost:#{server_port}"
       @stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
-      @metadata = { k1: 'v1', k2: 'v2' }
       @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
       @resp = 'a_reply'
     end
@@ -247,7 +354,8 @@
       end
 
       it 'should send metadata to the server ok' do
-        th = run_client_streamer(@sent_msgs, @resp, @pass, **@metadata)
+        th = run_client_streamer(@sent_msgs, @resp, @pass,
+                                 expected_metadata: @metadata)
         expect(get_response(@stub)).to eq(@resp)
         th.join
       end
@@ -278,27 +386,50 @@
     end
 
     describe 'via a call operation' do
+      after(:each) do
+        # make sure op.wait doesn't hang, even if there's a bad status
+        @op.wait
+      end
       def get_response(stub, run_start_call_first: false)
-        op = stub.client_streamer(@method, @sent_msgs, noop, noop,
-                                  return_op: true, metadata: @metadata)
-        expect(op).to be_a(GRPC::ActiveCall::Operation)
-        op.start_call if run_start_call_first
-        result = op.execute
-        op.wait # make sure wait doesn't hang
+        @op = stub.client_streamer(@method, @sent_msgs, noop, noop,
+                                   return_op: true, metadata: @metadata)
+        expect(@op).to be_a(GRPC::ActiveCall::Operation)
+        @op.start_call if run_start_call_first
+        result = @op.execute
         result
       end
 
       it_behaves_like 'client streaming'
 
-      it 'sends metadata to the server ok when running start_call first' do
-        th = run_client_streamer(@sent_msgs, @resp, @pass, **@metadata)
-        expect(get_response(@stub, run_start_call_first: true)).to eq(@resp)
+      def run_op_view_metadata_test(run_start_call_first)
+        @server_initial_md = { 'sk1' => 'sv1', 'sk2' => 'sv2' }
+        @server_trailing_md = { 'tk1' => 'tv1', 'tk2' => 'tv2' }
+        th = run_client_streamer(
+          @sent_msgs, @resp, @pass,
+          expected_metadata: @metadata,
+          server_initial_md: @server_initial_md,
+          server_trailing_md: @server_trailing_md)
+        expect(
+          get_response(@stub,
+                       run_start_call_first: run_start_call_first)).to eq(@resp)
         th.join
       end
+
+      it 'sends metadata to the server ok when running start_call first' do
+        run_op_view_metadata_test(true)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) { |r| p r }
+      end
+
+      it 'does not crash when used after the call has been finished' do
+        run_op_view_metadata_test(false)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) { |r| p r }
+      end
     end
   end
 
-  describe '#server_streamer' do
+  describe '#server_streamer', server_streamer: true do
     before(:each) do
       @sent_msg = 'a_msg'
       @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
@@ -328,18 +459,63 @@
         server_port = create_test_server
         host = "localhost:#{server_port}"
         th = run_server_streamer(@sent_msg, @replys, @fail,
-                                 k1: 'v1', k2: 'v2')
+                                 expected_metadata: { k1: 'v1', k2: 'v2' })
         stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
         e = get_responses(stub)
         expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
         th.join
       end
+
+      it 'should raise ArgumentError if metadata contains invalid values' do
+        @metadata.merge!(k3: 3)
+        server_port = create_test_server
+        host = "localhost:#{server_port}"
+        stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
+        expect do
+          get_responses(stub)
+        end.to raise_error(ArgumentError,
+                           /Header values must be of type string or array/)
+      end
+
+      def run_server_streamer_against_client_with_unmarshal_error(
+        expected_input, replys)
+        wakey_thread do |notifier|
+          c = expect_server_to_be_invoked(notifier)
+          expect(c.remote_read).to eq(expected_input)
+          begin
+            replys.each { |r| c.remote_send(r) }
+          rescue GRPC::Core::CallError
+            # An attempt to write to the client might fail. This is ok
+            # because the client call is expected to fail when
+            # unmarshalling the first response, and to cancel the call,
+            # and there is a race as for when the server-side call will
+            # start to fail.
+            p 'remote_send failed (allowed because call expected to cancel)'
+          ensure
+            c.send_status(OK, 'OK', true)
+          end
+        end
+      end
+
+      it 'the call terminates when there is an unmarshalling error' do
+        server_port = create_test_server
+        host = "localhost:#{server_port}"
+        th = run_server_streamer_against_client_with_unmarshal_error(
+          @sent_msg, @replys)
+        stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
+
+        unmarshal = proc { fail(ArgumentError, 'test unmarshalling error') }
+        expect do
+          get_responses(stub, unmarshal: unmarshal).collect { |r| r }
+        end.to raise_error(ArgumentError, 'test unmarshalling error')
+        th.join
+      end
     end
 
     describe 'without a call operation' do
-      def get_responses(stub)
-        e = stub.server_streamer(@method, @sent_msg, noop, noop,
-                                 metadata: { k1: 'v1', k2: 'v2' })
+      def get_responses(stub, unmarshal: noop)
+        e = stub.server_streamer(@method, @sent_msg, noop, unmarshal,
+                                 metadata: @metadata)
         expect(e).to be_a(Enumerator)
         e
       end
@@ -351,10 +527,10 @@
       after(:each) do
         @op.wait # make sure wait doesn't hang
       end
-      def get_responses(stub, run_start_call_first: false)
-        @op = stub.server_streamer(@method, @sent_msg, noop, noop,
+      def get_responses(stub, run_start_call_first: false, unmarshal: noop)
+        @op = stub.server_streamer(@method, @sent_msg, noop, unmarshal,
                                    return_op: true,
-                                   metadata: { k1: 'v1', k2: 'v2' })
+                                   metadata: @metadata)
         expect(@op).to be_a(GRPC::ActiveCall::Operation)
         @op.start_call if run_start_call_first
         e = @op.execute
@@ -364,20 +540,41 @@
 
       it_behaves_like 'server streaming'
 
-      it 'should send metadata to the server ok when start_call is run first' do
+      def run_op_view_metadata_test(run_start_call_first)
         server_port = create_test_server
         host = "localhost:#{server_port}"
-        th = run_server_streamer(@sent_msg, @replys, @fail,
-                                 k1: 'v1', k2: 'v2')
+        @server_initial_md = { 'sk1' => 'sv1', 'sk2' => 'sv2' }
+        @server_trailing_md = { 'tk1' => 'tv1', 'tk2' => 'tv2' }
+        th = run_server_streamer(
+          @sent_msg, @replys, @pass,
+          expected_metadata: @metadata,
+          server_initial_md: @server_initial_md,
+          server_trailing_md: @server_trailing_md)
         stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
-        e = get_responses(stub, run_start_call_first: true)
-        expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
+        e = get_responses(stub, run_start_call_first: run_start_call_first)
+        expect(e.collect { |r| r }).to eq(@replys)
         th.join
       end
+
+      it 'should send metadata to the server ok when start_call is run first' do
+        run_op_view_metadata_test(true)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) do |responses|
+          responses.each { |r| p r }
+        end
+      end
+
+      it 'does not crash when used after the call has been finished' do
+        run_op_view_metadata_test(false)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) do |responses|
+          responses.each { |r| p r }
+        end
+      end
     end
   end
 
-  describe '#bidi_streamer' do
+  describe '#bidi_streamer', bidi: true do
     before(:each) do
       @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
       @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
@@ -386,7 +583,7 @@
     end
 
     shared_examples 'bidi streaming' do
-      it 'supports sending all the requests first', bidi: true do
+      it 'supports sending all the requests first' do
         th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
                                                    @pass)
         stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
@@ -395,7 +592,7 @@
         th.join
       end
 
-      it 'supports client-initiated ping pong', bidi: true do
+      it 'supports client-initiated ping pong' do
         th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, true)
         stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
         e = get_responses(stub)
@@ -403,18 +600,53 @@
         th.join
       end
 
-      it 'supports a server-initiated ping pong', bidi: true do
+      it 'supports a server-initiated ping pong' do
         th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, false)
         stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
         e = get_responses(stub)
         expect(e.collect { |r| r }).to eq(@sent_msgs)
         th.join
       end
+
+      it 'should raise an error if the status is not ok' do
+        th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @fail, false)
+        stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+        e = get_responses(stub)
+        expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
+        th.join
+      end
+
+      it 'should raise ArgumentError if metadata contains invalid values' do
+        @metadata.merge!(k3: 3)
+        stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+        expect do
+          get_responses(stub).collect { |r| r }
+        end.to raise_error(ArgumentError,
+                           /Header values must be of type string or array/)
+      end
+
+      it 'terminates if the call fails to start' do
+        # don't start the server
+        stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+        expect do
+          get_responses(stub, deadline: from_relative_time(0)).collect { |r| r }
+        end.to raise_error(GRPC::BadStatus)
+      end
+
+      it 'should send metadata to the server ok' do
+        th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, true,
+                                              expected_metadata: @metadata)
+        stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+        e = get_responses(stub)
+        expect(e.collect { |r| r }).to eq(@sent_msgs)
+        th.join
+      end
     end
 
     describe 'without a call operation' do
-      def get_responses(stub)
-        e = stub.bidi_streamer(@method, @sent_msgs, noop, noop)
+      def get_responses(stub, deadline: nil)
+        e = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
+                               metadata: @metadata, deadline: deadline)
         expect(e).to be_a(Enumerator)
         e
       end
@@ -426,9 +658,10 @@
       after(:each) do
         @op.wait # make sure wait doesn't hang
       end
-      def get_responses(stub, run_start_call_first: false)
+      def get_responses(stub, run_start_call_first: false, deadline: nil)
         @op = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
-                                 return_op: true)
+                                 return_op: true,
+                                 metadata: @metadata, deadline: deadline)
         expect(@op).to be_a(GRPC::ActiveCall::Operation)
         @op.start_call if run_start_call_first
         e = @op.execute
@@ -438,27 +671,53 @@
 
       it_behaves_like 'bidi streaming'
 
-      it 'can run start_call before executing the call' do
-        th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
-                                                   @pass)
+      def run_op_view_metadata_test(run_start_call_first)
+        @server_initial_md = { 'sk1' => 'sv1', 'sk2' => 'sv2' }
+        @server_trailing_md = { 'tk1' => 'tv1', 'tk2' => 'tv2' }
+        th = run_bidi_streamer_echo_ping_pong(
+          @sent_msgs, @pass, true,
+          expected_metadata: @metadata,
+          server_initial_md: @server_initial_md,
+          server_trailing_md: @server_trailing_md)
         stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
-        e = get_responses(stub, run_start_call_first: true)
-        expect(e.collect { |r| r }).to eq(@replys)
+        e = get_responses(stub, run_start_call_first: run_start_call_first)
+        expect(e.collect { |r| r }).to eq(@sent_msgs)
         th.join
       end
+
+      it 'can run start_call before executing the call' do
+        run_op_view_metadata_test(true)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) do |responses|
+          responses.each { |r| p r }
+        end
+      end
+
+      it 'doesnt crash when op_view used after call has finished' do
+        run_op_view_metadata_test(false)
+        check_op_view_of_finished_client_call(
+          @op, @server_initial_md, @server_trailing_md) do |responses|
+          responses.each { |r| p r }
+        end
+      end
     end
   end
 
-  def run_server_streamer(expected_input, replys, status, **kw)
-    wanted_metadata = kw.clone
+  def run_server_streamer(expected_input, replys, status,
+                          expected_metadata: {},
+                          server_initial_md: {},
+                          server_trailing_md: {})
+    wanted_metadata = expected_metadata.clone
     wakey_thread do |notifier|
-      c = expect_server_to_be_invoked(notifier)
+      c = expect_server_to_be_invoked(
+        notifier, metadata_to_send: server_initial_md)
       wanted_metadata.each do |k, v|
         expect(c.metadata[k.to_s]).to eq(v)
       end
       expect(c.remote_read).to eq(expected_input)
       replys.each { |r| c.remote_send(r) }
-      c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
+      c.send_status(status, status == @pass ? 'OK' : 'NOK', true,
+                    metadata: server_trailing_md)
     end
   end
 
@@ -472,9 +731,17 @@
     end
   end
 
-  def run_bidi_streamer_echo_ping_pong(expected_inputs, status, client_starts)
+  def run_bidi_streamer_echo_ping_pong(expected_inputs, status, client_starts,
+                                       expected_metadata: {},
+                                       server_initial_md: {},
+                                       server_trailing_md: {})
+    wanted_metadata = expected_metadata.clone
     wakey_thread do |notifier|
-      c = expect_server_to_be_invoked(notifier)
+      c = expect_server_to_be_invoked(
+        notifier, metadata_to_send: server_initial_md)
+      wanted_metadata.each do |k, v|
+        expect(c.metadata[k.to_s]).to eq(v)
+      end
       expected_inputs.each do |i|
         if client_starts
           expect(c.remote_read).to eq(i)
@@ -484,33 +751,44 @@
           expect(c.remote_read).to eq(i)
         end
       end
-      c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
+      c.send_status(status, status == @pass ? 'OK' : 'NOK', true,
+                    metadata: server_trailing_md)
     end
   end
 
-  def run_client_streamer(expected_inputs, resp, status, **kw)
-    wanted_metadata = kw.clone
+  def run_client_streamer(expected_inputs, resp, status,
+                          expected_metadata: {},
+                          server_initial_md: {},
+                          server_trailing_md: {})
+    wanted_metadata = expected_metadata.clone
     wakey_thread do |notifier|
-      c = expect_server_to_be_invoked(notifier)
+      c = expect_server_to_be_invoked(
+        notifier, metadata_to_send: server_initial_md)
       expected_inputs.each { |i| expect(c.remote_read).to eq(i) }
       wanted_metadata.each do |k, v|
         expect(c.metadata[k.to_s]).to eq(v)
       end
       c.remote_send(resp)
-      c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
+      c.send_status(status, status == @pass ? 'OK' : 'NOK', true,
+                    metadata: server_trailing_md)
     end
   end
 
-  def run_request_response(expected_input, resp, status, **kw)
-    wanted_metadata = kw.clone
+  def run_request_response(expected_input, resp, status,
+                           expected_metadata: {},
+                           server_initial_md: {},
+                           server_trailing_md: {})
+    wanted_metadata = expected_metadata.clone
     wakey_thread do |notifier|
-      c = expect_server_to_be_invoked(notifier)
+      c = expect_server_to_be_invoked(
+        notifier, metadata_to_send: server_initial_md)
       expect(c.remote_read).to eq(expected_input)
       wanted_metadata.each do |k, v|
         expect(c.metadata[k.to_s]).to eq(v)
       end
       c.remote_send(resp)
-      c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
+      c.send_status(status, status == @pass ? 'OK' : 'NOK', true,
+                    metadata: server_trailing_md)
     end
   end
 
@@ -528,13 +806,13 @@
     @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
   end
 
-  def expect_server_to_be_invoked(notifier)
+  def expect_server_to_be_invoked(notifier, metadata_to_send: nil)
     @server.start
     notifier.notify(nil)
     recvd_rpc = @server.request_call
     recvd_call = recvd_rpc.call
     recvd_call.metadata = recvd_rpc.metadata
-    recvd_call.run_batch(SEND_INITIAL_METADATA => nil)
+    recvd_call.run_batch(SEND_INITIAL_METADATA => metadata_to_send)
     GRPC::ActiveCall.new(recvd_call, noop, noop, INFINITE_FUTURE,
                          metadata_received: true)
   end
diff --git a/src/ruby/spec/generic/rpc_desc_spec.rb b/src/ruby/spec/generic/rpc_desc_spec.rb
index 100e9e8..be578c4 100644
--- a/src/ruby/spec/generic/rpc_desc_spec.rb
+++ b/src/ruby/spec/generic/rpc_desc_spec.rb
@@ -38,14 +38,14 @@
 
   shared_examples 'it handles errors' do
     it 'sends the specified status if BadStatus is raised' do
-      expect(@call).to receive(:remote_read).once.and_return(Object.new)
+      expect(@call).to receive(:read_unary_request).once.and_return(Object.new)
       expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
                                                        metadata: {})
       this_desc.run_server_method(@call, method(:bad_status))
     end
 
     it 'sends status UNKNOWN if other StandardErrors are raised' do
-      expect(@call).to receive(:remote_read).once.and_return(Object.new)
+      expect(@call).to receive(:read_unary_request).once.and_return(Object.new)
       expect(@call).to receive(:send_status).once.with(UNKNOWN,
                                                        arg_error_msg,
                                                        false, metadata: {})
@@ -53,7 +53,7 @@
     end
 
     it 'absorbs CallError with no further action' do
-      expect(@call).to receive(:remote_read).once.and_raise(CallError)
+      expect(@call).to receive(:read_unary_request).once.and_raise(CallError)
       blk = proc do
         this_desc.run_server_method(@call, method(:fake_reqresp))
       end
@@ -75,7 +75,7 @@
 
       it 'sends a response and closes the stream if there no errors' do
         req = Object.new
-        expect(@call).to receive(:remote_read).once.and_return(req)
+        expect(@call).to receive(:read_unary_request).once.and_return(req)
         expect(@call).to receive(:output_metadata).once.and_return(fake_md)
         expect(@call).to receive(:server_unary_response).once
           .with(@ok_response, trailing_metadata: fake_md)
@@ -133,7 +133,7 @@
 
       it 'sends a response and closes the stream if there no errors' do
         req = Object.new
-        expect(@call).to receive(:remote_read).once.and_return(req)
+        expect(@call).to receive(:read_unary_request).once.and_return(req)
         expect(@call).to receive(:remote_send).twice.with(@ok_response)
         expect(@call).to receive(:output_metadata).and_return(fake_md)
         expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index 9633a82..e4fe594 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -111,6 +111,73 @@
 
 SlowStub = SlowService.rpc_stub_class
 
+# A test service that allows a synchronized RPC cancellation
+class SynchronizedCancellationService
+  include GRPC::GenericService
+  rpc :an_rpc, EchoMsg, EchoMsg
+  attr_reader :received_md, :delay
+
+  # notify_request_received and wait_until_rpc_cancelled are
+  # callbacks to synchronously allow the client to proceed with
+  # cancellation (after the unary request has been received),
+  # and to synchronously wait until the client has cancelled the
+  # current RPC.
+  def initialize(notify_request_received, wait_until_rpc_cancelled)
+    @notify_request_received = notify_request_received
+    @wait_until_rpc_cancelled = wait_until_rpc_cancelled
+  end
+
+  def an_rpc(req, _call)
+    GRPC.logger.info('starting a synchronusly cancelled rpc')
+    @notify_request_received.call(req)
+    @wait_until_rpc_cancelled.call
+    req  # send back the req as the response
+  end
+end
+
+SynchronizedCancellationStub = SynchronizedCancellationService.rpc_stub_class
+
+# a test service that hangs onto call objects
+# and uses them after the server-side call has been
+# finished
+class CheckCallAfterFinishedService
+  include GRPC::GenericService
+  rpc :an_rpc, EchoMsg, EchoMsg
+  rpc :a_client_streaming_rpc, stream(EchoMsg), EchoMsg
+  rpc :a_server_streaming_rpc, EchoMsg, stream(EchoMsg)
+  rpc :a_bidi_rpc, stream(EchoMsg), stream(EchoMsg)
+  attr_reader :server_side_call
+
+  def an_rpc(req, call)
+    fail 'shouldnt reuse service' unless @server_side_call.nil?
+    @server_side_call = call
+    req
+  end
+
+  def a_client_streaming_rpc(call)
+    fail 'shouldnt reuse service' unless @server_side_call.nil?
+    @server_side_call = call
+    # iterate through requests so call can complete
+    call.each_remote_read.each { |r| p r }
+    EchoMsg.new
+  end
+
+  def a_server_streaming_rpc(_, call)
+    fail 'shouldnt reuse service' unless @server_side_call.nil?
+    @server_side_call = call
+    [EchoMsg.new, EchoMsg.new]
+  end
+
+  def a_bidi_rpc(requests, call)
+    fail 'shouldnt reuse service' unless @server_side_call.nil?
+    @server_side_call = call
+    requests.each { |r| p r }
+    [EchoMsg.new, EchoMsg.new]
+  end
+end
+
+CheckCallAfterFinishedServiceStub = CheckCallAfterFinishedService.rpc_stub_class
+
 describe GRPC::RpcServer do
   RpcServer = GRPC::RpcServer
   StatusCodes = GRPC::Core::StatusCodes
@@ -343,20 +410,64 @@
       end
 
       it 'should handle cancellation correctly', server: true do
-        service = SlowService.new
+        request_received = false
+        request_received_mu = Mutex.new
+        request_received_cv = ConditionVariable.new
+        notify_request_received = proc do |req|
+          request_received_mu.synchronize do
+            fail 'req is nil' if req.nil?
+            expect(req.is_a?(EchoMsg)).to be true
+            fail 'test bug - already set' if request_received
+            request_received = true
+            request_received_cv.signal
+          end
+        end
+
+        rpc_cancelled = false
+        rpc_cancelled_mu = Mutex.new
+        rpc_cancelled_cv = ConditionVariable.new
+        wait_until_rpc_cancelled = proc do
+          rpc_cancelled_mu.synchronize do
+            loop do
+              break if rpc_cancelled
+              rpc_cancelled_cv.wait(rpc_cancelled_mu)
+            end
+          end
+        end
+
+        service = SynchronizedCancellationService.new(notify_request_received,
+                                                      wait_until_rpc_cancelled)
         @srv.handle(service)
-        t = Thread.new { @srv.run }
+        srv_thd = Thread.new { @srv.run }
         @srv.wait_till_running
         req = EchoMsg.new
-        stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
-        op = stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }, return_op: true)
-        Thread.new do  # cancel the call
-          sleep 0.1
-          op.cancel
+        stub = SynchronizedCancellationStub.new(@host,
+                                                :this_channel_is_insecure,
+                                                **client_opts)
+        op = stub.an_rpc(req, return_op: true)
+
+        client_thd = Thread.new do
+          expect { op.execute }.to raise_error GRPC::Cancelled
         end
-        expect { op.execute }.to raise_error GRPC::Cancelled
+
+        request_received_mu.synchronize do
+          loop do
+            break if request_received
+            request_received_cv.wait(request_received_mu)
+          end
+        end
+
+        op.cancel
+
+        rpc_cancelled_mu.synchronize do
+          fail 'test bug - already set' if rpc_cancelled
+          rpc_cancelled = true
+          rpc_cancelled_cv.signal
+        end
+
+        client_thd.join
         @srv.stop
-        t.join
+        srv_thd.join
       end
 
       it 'should handle multiple parallel requests', server: true do
@@ -505,5 +616,109 @@
         t.join
       end
     end
+
+    context 'when call objects are used after calls have completed' do
+      before(:each) do
+        server_opts = {
+          poll_period: 1
+        }
+        @srv = RpcServer.new(**server_opts)
+        alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+        @alt_host = "0.0.0.0:#{alt_port}"
+
+        @service = CheckCallAfterFinishedService.new
+        @srv.handle(@service)
+        @srv_thd  = Thread.new { @srv.run }
+        @srv.wait_till_running
+      end
+
+      # check that the server-side call is still in a usable state even
+      # after it has finished
+      def check_single_req_view_of_finished_call(call)
+        common_check_of_finished_server_call(call)
+
+        expect(call.peer).to be_a(String)
+        expect(call.peer_cert).to be(nil)
+      end
+
+      def check_multi_req_view_of_finished_call(call)
+        common_check_of_finished_server_call(call)
+
+        expect do
+          call.each_remote_read.each { |r| p r }
+        end.to raise_error(GRPC::Core::CallError)
+      end
+
+      def common_check_of_finished_server_call(call)
+        expect do
+          call.merge_metadata_to_send({})
+        end.to raise_error(RuntimeError)
+
+        expect do
+          call.send_initial_metadata
+        end.to_not raise_error
+
+        expect(call.cancelled?).to be(false)
+        expect(call.metadata).to be_a(Hash)
+        expect(call.metadata['user-agent']).to be_a(String)
+
+        expect(call.metadata_sent).to be(true)
+        expect(call.output_metadata).to eq({})
+        expect(call.metadata_to_send).to eq({})
+        expect(call.deadline.is_a?(Time)).to be(true)
+      end
+
+      it 'should not crash when call used after an unary call is finished' do
+        req = EchoMsg.new
+        stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
+                                                     :this_channel_is_insecure)
+        resp = stub.an_rpc(req)
+        expect(resp).to be_a(EchoMsg)
+        @srv.stop
+        @srv_thd.join
+
+        check_single_req_view_of_finished_call(@service.server_side_call)
+      end
+
+      it 'should not crash when call used after client streaming finished' do
+        requests = [EchoMsg.new, EchoMsg.new]
+        stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
+                                                     :this_channel_is_insecure)
+        resp = stub.a_client_streaming_rpc(requests)
+        expect(resp).to be_a(EchoMsg)
+        @srv.stop
+        @srv_thd.join
+
+        check_multi_req_view_of_finished_call(@service.server_side_call)
+      end
+
+      it 'should not crash when call used after server streaming finished' do
+        req = EchoMsg.new
+        stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
+                                                     :this_channel_is_insecure)
+        responses = stub.a_server_streaming_rpc(req)
+        responses.each do |r|
+          expect(r).to be_a(EchoMsg)
+        end
+        @srv.stop
+        @srv_thd.join
+
+        check_single_req_view_of_finished_call(@service.server_side_call)
+      end
+
+      it 'should not crash when call used after a bidi call is finished' do
+        requests = [EchoMsg.new, EchoMsg.new]
+        stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
+                                                     :this_channel_is_insecure)
+        responses = stub.a_bidi_rpc(requests)
+        responses.each do |r|
+          expect(r).to be_a(EchoMsg)
+        end
+        @srv.stop
+        @srv_thd.join
+
+        check_multi_req_view_of_finished_call(@service.server_side_call)
+      end
+    end
   end
 end
diff --git a/src/ruby/spec/testdata/client.key b/src/ruby/spec/testdata/client.key
new file mode 100644
index 0000000..f48d073
--- /dev/null
+++ b/src/ruby/spec/testdata/client.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAOxUR9uhvhbeVUIM
+s5WbH0px0mehl2+6sZpNjzvE2KimZpHzMJHukVH0Ffkvhs0b8+S5Ut9VNUAqd3IM
+JCCAEGtRNoQhM1t9Yr2zAckSvbRacp+FL/Cj9eDmyo00KsVGaeefA4Dh4OW+ZhkT
+NKcldXqkSuj1sEf244JZYuqZp6/tAgMBAAECgYEAi2NSVqpZMafE5YYUTcMGe6QS
+k2jtpsqYgggI2RnLJ/2tNZwYI5pwP8QVSbnMaiF4gokD5hGdrNDfTnb2v+yIwYEH
+0w8+oG7Z81KodsiZSIDJfTGsAZhVNwOz9y0VD8BBZZ1/274Zh52AUKLjZS/ZwIbS
+W2ywya855dPnH/wj+0ECQQD9X8D920kByTNHhBG18biAEZ4pxs9f0OAG8333eVcI
+w2lJDLsYDZrCB2ocgA3lUdozlzPC7YDYw8reg0tkiRY5AkEA7sdNzOeQsQRn7++5
+0bP9DtT/iON1gbfxRzCfCfXdoOtfQWIzTePWtURt9X/5D9NofI0Rg5W2oGy/MLe5
+/sXHVQJBAIup5XrJDkQywNZyAUU2ecn2bCWBFjwtqd+LBmuMciI9fOKsZtEKZrz/
+U0lkeMRoSwvXE8wmGLjjrAbdfohrXFkCQQDZEx/LtIl6JINJQiswVe0tWr6k+ASP
+1WXoTm+HYpoF/XUvv9LccNF1IazFj34hwRQwhx7w/V52Ieb+p0jUMYGxAkEAjDhd
+9pBO1fKXWiXzi9ZKfoyTNcUq3eBSVKwPG2nItg5ycXengjT5sgcWDnciIzW7BIVI
+JiqOszq9GWESErAatg==
+-----END PRIVATE KEY-----
diff --git a/src/ruby/spec/testdata/client.pem b/src/ruby/spec/testdata/client.pem
new file mode 100644
index 0000000..e332091
--- /dev/null
+++ b/src/ruby/spec/testdata/client.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHzCCAYgCAQEwDQYJKoZIhvcNAQEFBQAwVjELMAkGA1UEBhMCQVUxEzARBgNV
+BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
+ZDEPMA0GA1UEAwwGdGVzdGNhMB4XDTE0MDcxNzIzNTYwMloXDTI0MDcxNDIzNTYw
+MlowWjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKdGVzdGNsaWVudDCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7FRH26G+Ft5VQgyzlZsfSnHSZ6GX
+b7qxmk2PO8TYqKZmkfMwke6RUfQV+S+GzRvz5LlS31U1QCp3cgwkIIAQa1E2hCEz
+W31ivbMByRK9tFpyn4Uv8KP14ObKjTQqxUZp558DgOHg5b5mGRM0pyV1eqRK6PWw
+R/bjglli6pmnr+0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAStSm5PM7ubROiKK6/
+T2FkKlhiTOx+Ryenm3Eio59emq+jXl+1nhPySX5G2PQzSR5vd1dIhwgZSR4Gyttk
+tRZ57k/NI1brUW8joiEOMJA/Mr7H7asx7wIRYDE91Fs8GkKWd5LhoPAQj+qdG35C
+OO+svdkmqH0KZo320ZUqdl2ooQ==
+-----END CERTIFICATE-----
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 051a475..0588787 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -1233,7 +1233,7 @@
   	$(Q) mkdir -p `dirname $@`
   	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-  $(GENDIR)/${p}.grpc.pb.cc: ${p}.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) ${' '.join('$(GENDIR)/%s.pb.cc $(GENDIR)/%s.grpc.pb.cc' % (q,q) for q in proto_deps.get(p, []))}
+  $(GENDIR)/${p}.grpc.pb.cc: ${p}.proto $(GENDIR)/${p}.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) ${' '.join('$(GENDIR)/%s.pb.cc $(GENDIR)/%s.grpc.pb.cc' % (q,q) for q in proto_deps.get(p, []))}
   	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
   	$(Q) mkdir -p `dirname $@`
   	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=${pluginflags}$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template
index b7560fe..adb7d9f 100644
--- a/templates/binding.gyp.template
+++ b/templates/binding.gyp.template
@@ -165,19 +165,22 @@
         }],
         ['OS == "mac"', {
           'xcode_settings': {
-            'MACOSX_DEPLOYMENT_TARGET': '10.9'
+            % if defaults['global'].get('CPPFLAGS', None) is not None:
+            'OTHER_CFLAGS': [
+              % for item in defaults['global'].get('CPPFLAGS').split():
+                '${item}',
+              % endfor
+            ],
+            'OTHER_CPLUSPLUSFLAGS': [
+              % for item in defaults['global'].get('CPPFLAGS').split():
+                '${item}',
+              % endfor
+              '-stdlib=libc++',
+              '-std=c++11',
+              '-Wno-error=deprecated-declarations'
+            ],
+            % endif
           },
-          % if defaults['global'].get('CPPFLAGS', None) is not None:
-          'OTHER_CFLAGS': [
-            % for item in defaults['global'].get('CPPFLAGS').split():
-              '${item}',
-            % endfor
-          ],
-          'OTHER_CPLUSPLUSFLAGS': [
-            '-stdlib=libc++',
-            '-std=c++11'
-          ],
-          % endif
         }]
       ]
     },
@@ -201,6 +204,13 @@
               '${source}',
               % endfor
             ],
+            'conditions': [
+              ['OS == "mac"', {
+                'xcode_settings': {
+                  'MACOSX_DEPLOYMENT_TARGET': '10.9'
+                }
+              }]
+            ]
           },
           % endif
           % endfor
@@ -282,6 +292,13 @@
           '${source}',
           % endfor
         ],
+        'conditions': [
+          ['OS == "mac"', {
+            'xcode_settings': {
+              'MACOSX_DEPLOYMENT_TARGET': '10.9'
+            }
+          }]
+        ]
       },
       % endif
       % endfor
@@ -317,6 +334,11 @@
             'ldflags': [
               '-Wl,-wrap,memcpy'
             ]
+          }],
+          ['OS == "mac"', {
+            'xcode_settings': {
+              'MACOSX_DEPLOYMENT_TARGET': '10.9'
+            }
           }]
         ],
         "target_name": "${module.name}",
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index 3d54534..cfc13cf 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -135,7 +135,7 @@
       ss.header_mappings_dir = '.'
       ss.libraries = 'z'
       ss.dependency "#{s.name}/Interface", version
-      ss.dependency 'BoringSSL', '~> 8.0'
+      ss.dependency 'BoringSSL', '~> 9.0'
       ss.dependency 'nanopb', '~> 0.3'
 
       # To save you from scrolling, this is the last part of the podspec.
diff --git "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template" "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
index 24c167d..b822341 100644
--- "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
+++ "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
@@ -103,7 +103,7 @@
     s.preserve_paths = plugin
 
     # Restrict the protoc version to the one supported by this plugin.
-    s.dependency '!ProtoCompiler', '3.2.0'
+    s.dependency '!ProtoCompiler', '3.3.0'
     # For the Protobuf dependency not to complain:
     s.ios.deployment_target = '7.0'
     s.osx.deployment_target = '10.9'
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
index 3f5b6cf..1f6755e 100644
--- a/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
+++ b/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
@@ -57,22 +57,24 @@
     apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && ${'\\'}
     gcloud config set component_manager/disable_update_check true
 
-  # Download and install grpc-java
+  # Install Android SDK
   WORKDIR /
-  RUN git clone https://github.com/grpc/grpc-java.git
-  WORKDIR /grpc-java
-  RUN ./gradlew install
+  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"
 
-  # Setup the Android SDK licenses
-  ENV ANDROID_HOME "/grpc-java/android-interop-testing/.android"
-  RUN mkdir -p "<%text>${ANDROID_HOME}</%text>/licenses"
-  RUN echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "<%text>${ANDROID_HOME}</%text>/licenses/android-sdk-license"
-  RUN echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "<%text>${ANDROID_HOME}</%text>/licenses/android-sdk-preview-license"
-
-  # Build the Android interop apks
-  WORKDIR /grpc-java/android-interop-testing
-  RUN ../gradlew assembleDebug
-  RUN ../gradlew assembleDebugAndroidTest
+  # Reset the working directory
+  WORKDIR /
 
   # Define the default command.
   CMD ["bash"]
diff --git a/test/core/bad_client/BUILD b/test/core/bad_client/BUILD
index c23c046..8cc9dfa 100644
--- a/test/core/bad_client/BUILD
+++ b/test/core/bad_client/BUILD
@@ -14,6 +14,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 licenses(["notice"])  # Apache v2
 
 load(":generate_tests.bzl", "grpc_bad_client_tests")
diff --git a/test/core/bad_ssl/BUILD b/test/core/bad_ssl/BUILD
index cb285d0..e13d432 100644
--- a/test/core/bad_ssl/BUILD
+++ b/test/core/bad_ssl/BUILD
@@ -14,6 +14,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 licenses(["notice"])  # Apache v2
 
 load(":generate_tests.bzl", "grpc_bad_ssl_tests")
diff --git a/test/core/census/BUILD b/test/core/census/BUILD
index 5de149a..988d9a8 100644
--- a/test/core/census/BUILD
+++ b/test/core/census/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "context_test",
     srcs = ["context_test.c"],
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index da2389a..18dd112 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "channel_args_test",
     srcs = ["channel_args_test.c"],
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index 41ba792..7fc5b97 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/client_channel/resolvers/BUILD b/test/core/client_channel/resolvers/BUILD
index 59826ae..8af4a2d 100644
--- a/test/core/client_channel/resolvers/BUILD
+++ b/test/core/client_channel/resolvers/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "dns_resolver_connectivity_test",
     srcs = ["dns_resolver_connectivity_test.c"],
diff --git a/test/core/compression/BUILD b/test/core/compression/BUILD
index a4fefc5..e4432b3 100644
--- a/test/core/compression/BUILD
+++ b/test/core/compression/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "algorithm_test",
     srcs = ["algorithm_test.c"],
diff --git a/test/core/compression/stream_compression_test.c b/test/core/compression/stream_compression_test.c
new file mode 100644
index 0000000..e576507
--- /dev/null
+++ b/test/core/compression/stream_compression_test.c
@@ -0,0 +1,292 @@
+/*
+ *
+ * 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 <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/slice_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/compression/stream_compression.h"
+
+static void generate_random_payload(char *payload, size_t size) {
+  size_t i;
+  static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
+  for (i = 0; i < size - 1; ++i) {
+    payload[i] = chars[rand() % (int)(sizeof(chars) - 1)];
+  }
+  payload[size - 1] = '\0';
+}
+
+static bool slice_buffer_equals_string(grpc_slice_buffer *buf,
+                                       const char *str) {
+  size_t i;
+  if (buf->length != strlen(str)) {
+    return false;
+  }
+  size_t pointer = 0;
+  for (i = 0; i < buf->count; i++) {
+    size_t slice_len = GRPC_SLICE_LENGTH(buf->slices[i]);
+    if (0 != strncmp(str + pointer,
+                     (char *)GRPC_SLICE_START_PTR(buf->slices[i]), slice_len)) {
+      return false;
+    }
+    pointer += slice_len;
+  }
+  return true;
+}
+
+static void test_stream_compression_simple_compress_decompress() {
+  const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest";
+  grpc_slice_buffer source, relay, sink;
+  grpc_slice_buffer_init(&source);
+  grpc_slice_buffer_init(&relay);
+  grpc_slice_buffer_init(&sink);
+  grpc_stream_compression_context *compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  grpc_stream_compression_context *decompress_ctx =
+      grpc_stream_compression_context_create(
+          GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  grpc_slice slice = grpc_slice_from_static_string(test_str);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  bool end_of_context;
+  size_t output_size;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(output_size == sizeof(test_str) - 1);
+  grpc_stream_compression_context_destroy(compress_ctx);
+  grpc_stream_compression_context_destroy(decompress_ctx);
+
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str));
+
+  grpc_slice_buffer_destroy(&source);
+  grpc_slice_buffer_destroy(&relay);
+  grpc_slice_buffer_destroy(&sink);
+}
+
+static void
+test_stream_compression_simple_compress_decompress_with_output_size_constraint() {
+  const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest";
+  grpc_slice_buffer source, relay, sink;
+  grpc_slice_buffer_init(&source);
+  grpc_slice_buffer_init(&relay);
+  grpc_slice_buffer_init(&sink);
+  grpc_stream_compression_context *compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  grpc_stream_compression_context *decompress_ctx =
+      grpc_stream_compression_context_create(
+          GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  grpc_slice slice = grpc_slice_from_static_string(test_str);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  grpc_stream_compression_context_destroy(compress_ctx);
+
+  bool end_of_context;
+  size_t output_size;
+  size_t max_output_size = 2;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    max_output_size, &end_of_context));
+  GPR_ASSERT(output_size == max_output_size);
+  GPR_ASSERT(end_of_context == false);
+  grpc_slice slice_recv = grpc_slice_buffer_take_first(&sink);
+  char *str_recv = (char *)GRPC_SLICE_START_PTR(slice_recv);
+  GPR_ASSERT(GRPC_SLICE_LENGTH(slice_recv) == max_output_size);
+  GPR_ASSERT(0 == strncmp(test_str, str_recv, max_output_size));
+  grpc_slice_unref(slice_recv);
+
+  size_t remaining_size = sizeof(test_str) - 1 - max_output_size;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    remaining_size, &end_of_context));
+  GPR_ASSERT(output_size == remaining_size);
+  GPR_ASSERT(end_of_context == true);
+
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str + max_output_size));
+
+  grpc_stream_compression_context_destroy(decompress_ctx);
+  grpc_slice_buffer_destroy(&source);
+  grpc_slice_buffer_destroy(&relay);
+  grpc_slice_buffer_destroy(&sink);
+}
+
+#define LARGE_DATA_SIZE (1024 * 1024)
+static void
+test_stream_compression_simple_compress_decompress_with_large_data() {
+  char *test_str = gpr_malloc(LARGE_DATA_SIZE * sizeof(char));
+  generate_random_payload(test_str, LARGE_DATA_SIZE);
+  grpc_slice_buffer source, relay, sink;
+  grpc_slice_buffer_init(&source);
+  grpc_slice_buffer_init(&relay);
+  grpc_slice_buffer_init(&sink);
+  grpc_stream_compression_context *compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  grpc_stream_compression_context *decompress_ctx =
+      grpc_stream_compression_context_create(
+          GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  grpc_slice slice = grpc_slice_from_static_string(test_str);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  bool end_of_context;
+  size_t output_size;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(output_size == LARGE_DATA_SIZE - 1);
+  grpc_stream_compression_context_destroy(compress_ctx);
+  grpc_stream_compression_context_destroy(decompress_ctx);
+
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str));
+
+  grpc_slice_buffer_destroy(&source);
+  grpc_slice_buffer_destroy(&relay);
+  grpc_slice_buffer_destroy(&sink);
+  gpr_free(test_str);
+}
+
+static void test_stream_compression_drop_context() {
+  const char test_str[] = "aaaaaaabbbbbbbccccccc";
+  const char test_str2[] = "dddddddeeeeeeefffffffggggg";
+  grpc_slice_buffer source, relay, sink;
+  grpc_slice_buffer_init(&source);
+  grpc_slice_buffer_init(&relay);
+  grpc_slice_buffer_init(&sink);
+  grpc_stream_compression_context *compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  grpc_slice slice = grpc_slice_from_static_string(test_str);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  grpc_stream_compression_context_destroy(compress_ctx);
+
+  compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  slice = grpc_slice_from_static_string(test_str2);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  grpc_stream_compression_context_destroy(compress_ctx);
+
+  /* Concatenate the two compressed sliced into one to test decompressing two
+   * contexts */
+  grpc_slice slice1 = grpc_slice_buffer_take_first(&relay);
+  grpc_slice slice2 = grpc_slice_buffer_take_first(&relay);
+  grpc_slice slice3 =
+      grpc_slice_malloc(GRPC_SLICE_LENGTH(slice1) + GRPC_SLICE_LENGTH(slice2));
+  memcpy(GRPC_SLICE_START_PTR(slice3), GRPC_SLICE_START_PTR(slice1),
+         GRPC_SLICE_LENGTH(slice1));
+  memcpy(GRPC_SLICE_START_PTR(slice3) + GRPC_SLICE_LENGTH(slice1),
+         GRPC_SLICE_START_PTR(slice2), GRPC_SLICE_LENGTH(slice2));
+  grpc_slice_unref(slice1);
+  grpc_slice_unref(slice2);
+  grpc_slice_buffer_add(&relay, slice3);
+
+  grpc_stream_compression_context *decompress_ctx =
+      grpc_stream_compression_context_create(
+          GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  bool end_of_context;
+  size_t output_size;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(end_of_context == true);
+  GPR_ASSERT(output_size == sizeof(test_str) - 1);
+
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str));
+  grpc_stream_compression_context_destroy(decompress_ctx);
+  grpc_slice_buffer_destroy(&sink);
+
+  grpc_slice_buffer_init(&sink);
+  decompress_ctx = grpc_stream_compression_context_create(
+      GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(end_of_context == true);
+  GPR_ASSERT(output_size == sizeof(test_str2) - 1);
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2));
+  grpc_stream_compression_context_destroy(decompress_ctx);
+
+  grpc_slice_buffer_destroy(&source);
+  grpc_slice_buffer_destroy(&relay);
+  grpc_slice_buffer_destroy(&sink);
+}
+
+static void test_stream_compression_sync_flush() {
+  const char test_str[] = "aaaaaaabbbbbbbccccccc";
+  const char test_str2[] = "dddddddeeeeeeefffffffggggg";
+  grpc_slice_buffer source, relay, sink;
+  grpc_slice_buffer_init(&source);
+  grpc_slice_buffer_init(&relay);
+  grpc_slice_buffer_init(&sink);
+  grpc_stream_compression_context *compress_ctx =
+      grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
+  grpc_slice slice = grpc_slice_from_static_string(test_str);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_SYNC));
+
+  grpc_stream_compression_context *decompress_ctx =
+      grpc_stream_compression_context_create(
+          GRPC_STREAM_COMPRESSION_DECOMPRESS);
+  bool end_of_context;
+  size_t output_size;
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(end_of_context == false);
+  GPR_ASSERT(output_size == sizeof(test_str) - 1);
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str));
+  grpc_slice_buffer_destroy(&sink);
+
+  grpc_slice_buffer_init(&sink);
+  slice = grpc_slice_from_static_string(test_str2);
+  grpc_slice_buffer_add(&source, slice);
+  GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL,
+                                  ~(size_t)0,
+                                  GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
+  grpc_stream_compression_context_destroy(compress_ctx);
+
+  GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
+                                    ~(size_t)0, &end_of_context));
+  GPR_ASSERT(end_of_context == true);
+  GPR_ASSERT(output_size == sizeof(test_str2) - 1);
+  GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2));
+  grpc_stream_compression_context_destroy(decompress_ctx);
+
+  grpc_slice_buffer_destroy(&source);
+  grpc_slice_buffer_destroy(&relay);
+  grpc_slice_buffer_destroy(&sink);
+}
+
+int main(int argc, char **argv) {
+  grpc_init();
+  test_stream_compression_simple_compress_decompress();
+  test_stream_compression_simple_compress_decompress_with_output_size_constraint();
+  test_stream_compression_simple_compress_decompress_with_large_data();
+  test_stream_compression_sync_flush();
+  test_stream_compression_drop_context();
+  grpc_shutdown();
+
+  return 0;
+}
diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD
index e27303c..9e788bf 100644
--- a/test/core/end2end/BUILD
+++ b/test/core/end2end/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load(":generate_tests.bzl", "grpc_end2end_tests")
 
 grpc_cc_library(
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index ae1db54..6a061a4 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -106,6 +106,8 @@
 extern void ping_pre_init(void);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
 extern void ping_pong_streaming_pre_init(void);
+extern void proxy_auth(grpc_end2end_test_config config);
+extern void proxy_auth_pre_init(void);
 extern void registered_call(grpc_end2end_test_config config);
 extern void registered_call_pre_init(void);
 extern void request_with_flags(grpc_end2end_test_config config);
@@ -181,6 +183,7 @@
   payload_pre_init();
   ping_pre_init();
   ping_pong_streaming_pre_init();
+  proxy_auth_pre_init();
   registered_call_pre_init();
   request_with_flags_pre_init();
   request_with_payload_pre_init();
@@ -244,6 +247,7 @@
     payload(config);
     ping(config);
     ping_pong_streaming(config);
+    proxy_auth(config);
     registered_call(config);
     request_with_flags(config);
     request_with_payload(config);
@@ -416,6 +420,10 @@
       ping_pong_streaming(config);
       continue;
     }
+    if (0 == strcmp("proxy_auth", argv[i])) {
+      proxy_auth(config);
+      continue;
+    }
     if (0 == strcmp("registered_call", argv[i])) {
       registered_call(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index d18dd9c..3fc7c3f 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -108,6 +108,8 @@
 extern void ping_pre_init(void);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
 extern void ping_pong_streaming_pre_init(void);
+extern void proxy_auth(grpc_end2end_test_config config);
+extern void proxy_auth_pre_init(void);
 extern void registered_call(grpc_end2end_test_config config);
 extern void registered_call_pre_init(void);
 extern void request_with_flags(grpc_end2end_test_config config);
@@ -184,6 +186,7 @@
   payload_pre_init();
   ping_pre_init();
   ping_pong_streaming_pre_init();
+  proxy_auth_pre_init();
   registered_call_pre_init();
   request_with_flags_pre_init();
   request_with_payload_pre_init();
@@ -248,6 +251,7 @@
     payload(config);
     ping(config);
     ping_pong_streaming(config);
+    proxy_auth(config);
     registered_call(config);
     request_with_flags(config);
     request_with_payload(config);
@@ -424,6 +428,10 @@
       ping_pong_streaming(config);
       continue;
     }
+    if (0 == strcmp("proxy_auth", argv[i])) {
+      proxy_auth(config);
+      continue;
+    }
     if (0 == strcmp("registered_call", argv[i])) {
       registered_call(config);
       continue;
diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c
index f8c88e5..6145892 100644
--- a/test/core/end2end/fixtures/h2_http_proxy.c
+++ b/test/core/end2end/fixtures/h2_http_proxy.c
@@ -47,11 +47,13 @@
     grpc_channel_args *client_args, grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
   memset(&f, 0, sizeof(f));
-
   fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data));
   const int server_port = grpc_pick_unused_port_or_die();
   gpr_join_host_port(&ffd->server_addr, "localhost", server_port);
-  ffd->proxy = grpc_end2end_http_proxy_create();
+
+  /* Passing client_args to proxy_create for the case of checking for proxy auth
+   */
+  ffd->proxy = grpc_end2end_http_proxy_create(client_args);
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(NULL);
@@ -64,8 +66,17 @@
                                   grpc_channel_args *client_args) {
   fullstack_fixture_data *ffd = f->fixture_data;
   char *proxy_uri;
-  gpr_asprintf(&proxy_uri, "http://%s",
-               grpc_end2end_http_proxy_get_proxy_name(ffd->proxy));
+
+  /* If testing for proxy auth, add credentials to proxy uri */
+  const grpc_arg *proxy_auth_arg =
+      grpc_channel_args_find(client_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS);
+  if (proxy_auth_arg == NULL || proxy_auth_arg->type != GRPC_ARG_STRING) {
+    gpr_asprintf(&proxy_uri, "http://%s",
+                 grpc_end2end_http_proxy_get_proxy_name(ffd->proxy));
+  } else {
+    gpr_asprintf(&proxy_uri, "http://%s@%s", proxy_auth_arg->value.string,
+                 grpc_end2end_http_proxy_get_proxy_name(ffd->proxy));
+  }
   gpr_setenv("http_proxy", proxy_uri);
   gpr_free(proxy_uri);
   f->client = grpc_insecure_channel_create(ffd->server_addr, client_args, NULL);
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 9cbaaa0..ee1d0b1 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -137,10 +137,11 @@
 
 static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_channel_credentials *ssl_creds =
       grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
-  grpc_call_credentials *oauth2_creds =
-      grpc_md_only_test_credentials_create("authorization", oauth2_md, 1);
+  grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
+      &exec_ctx, "authorization", oauth2_md, true /* is_async */);
   grpc_channel_credentials *ssl_oauth2_creds =
       grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
@@ -149,13 +150,10 @@
   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_oauth2_creds);
-  {
-    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_channel_args_destroy(&exec_ctx, new_client_args);
-    grpc_exec_ctx_finish(&exec_ctx);
-  }
+  grpc_channel_args_destroy(&exec_ctx, new_client_args);
   grpc_channel_credentials_release(ssl_creds);
   grpc_call_credentials_release(oauth2_creds);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static int fail_server_auth_check(grpc_channel_args *server_args) {
diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c
index 54693c4..a4cfc77 100644
--- a/test/core/end2end/fixtures/http_proxy_fixture.c
+++ b/test/core/end2end/fixtures/http_proxy_fixture.c
@@ -22,6 +22,7 @@
 
 #include <string.h>
 
+#include <grpc/grpc.h>
 #include <grpc/slice_buffer.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/atm.h>
@@ -46,7 +47,9 @@
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/iomgr/tcp_server.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/slice/b64.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/support/string.h"
 #include "test/core/util/port.h"
 
 struct grpc_end2end_http_proxy {
@@ -304,6 +307,28 @@
                       &conn->on_write_response_done);
 }
 
+/**
+ * Parses the proxy auth header value to check if it matches :-
+ * Basic <base64_encoded_expected_cred>
+ * Returns true if it matches, false otherwise
+ */
+static bool proxy_auth_header_matches(grpc_exec_ctx* exec_ctx,
+                                      char* proxy_auth_header_val,
+                                      char* expected_cred) {
+  GPR_ASSERT(proxy_auth_header_val != NULL);
+  GPR_ASSERT(expected_cred != NULL);
+  if (strncmp(proxy_auth_header_val, "Basic ", 6) != 0) {
+    return false;
+  }
+  proxy_auth_header_val += 6;
+  grpc_slice decoded_slice =
+      grpc_base64_decode(exec_ctx, proxy_auth_header_val, 0);
+  const bool header_matches =
+      grpc_slice_str_cmp(decoded_slice, expected_cred) == 0;
+  grpc_slice_unref_internal(exec_ctx, decoded_slice);
+  return header_matches;
+}
+
 // Callback to read the HTTP CONNECT request.
 // TODO(roth): Technically, for any of the failure modes handled by this
 // function, we should handle the error by returning an HTTP response to
@@ -352,6 +377,28 @@
     GRPC_ERROR_UNREF(error);
     return;
   }
+  // If proxy auth is being used, check if the header is present and as expected
+  const grpc_arg* proxy_auth_arg = grpc_channel_args_find(
+      conn->proxy->channel_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS);
+  if (proxy_auth_arg != NULL && proxy_auth_arg->type == GRPC_ARG_STRING) {
+    bool client_authenticated = false;
+    for (size_t i = 0; i < conn->http_request.hdr_count; i++) {
+      if (strcmp(conn->http_request.hdrs[i].key, "Proxy-Authorization") == 0) {
+        client_authenticated = proxy_auth_header_matches(
+            exec_ctx, conn->http_request.hdrs[i].value,
+            proxy_auth_arg->value.string);
+        break;
+      }
+    }
+    if (!client_authenticated) {
+      const char* msg = "HTTP Connect could not verify authentication";
+      error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(msg);
+      proxy_connection_failed(exec_ctx, conn, true /* is_client */,
+                              "HTTP proxy read request", error);
+      GRPC_ERROR_UNREF(error);
+      return;
+    }
+  }
   // Resolve address.
   grpc_resolved_addresses* resolved_addresses = NULL;
   error = grpc_blocking_resolve_address(conn->http_request.path, "80",
@@ -436,7 +483,8 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) {
+grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(
+    grpc_channel_args* args) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_end2end_http_proxy* proxy =
       (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy));
@@ -448,7 +496,7 @@
   gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port);
   gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name);
   // Create TCP server.
-  proxy->channel_args = grpc_channel_args_copy(NULL);
+  proxy->channel_args = grpc_channel_args_copy(args);
   grpc_error* error = grpc_tcp_server_create(
       &exec_ctx, NULL, proxy->channel_args, &proxy->server);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
diff --git a/test/core/end2end/fixtures/http_proxy_fixture.h b/test/core/end2end/fixtures/http_proxy_fixture.h
index a72162e..103bd08 100644
--- a/test/core/end2end/fixtures/http_proxy_fixture.h
+++ b/test/core/end2end/fixtures/http_proxy_fixture.h
@@ -16,11 +16,28 @@
  *
  */
 
+#ifndef GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H
+#define GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H
+
+#include <grpc/grpc.h>
+
+/* The test credentials being used for HTTP Proxy Authorization */
+#define GRPC_TEST_HTTP_PROXY_AUTH_CREDS "aladdin:opensesame"
+
+/* A channel arg key used to indicate that the channel uses proxy authorization.
+ * The value (string) should be the proxy auth credentials that should be
+ * checked.
+ */
+#define GRPC_ARG_HTTP_PROXY_AUTH_CREDS "grpc.test.proxy_auth"
+
 typedef struct grpc_end2end_http_proxy grpc_end2end_http_proxy;
 
-grpc_end2end_http_proxy* grpc_end2end_http_proxy_create();
+grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(
+    grpc_channel_args* args);
 
 void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy);
 
 const char* grpc_end2end_http_proxy_get_proxy_name(
     grpc_end2end_http_proxy* proxy);
+
+#endif /* GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H */
diff --git a/test/core/end2end/fixtures/inproc.c b/test/core/end2end/fixtures/inproc.c
new file mode 100644
index 0000000..6f742f0
--- /dev/null
+++ b/test/core/end2end/fixtures/inproc.c
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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 "test/core/end2end/end2end_tests.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/http/server/http_server_filter.h"
+#include "src/core/ext/transport/inproc/inproc_transport.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/server.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+typedef struct inproc_fixture_data {
+  bool dummy;  // reserved for future expansion. Struct can't be empty
+} inproc_fixture_data;
+
+static grpc_end2end_test_fixture inproc_create_fixture(
+    grpc_channel_args *client_args, grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  inproc_fixture_data *ffd = gpr_malloc(sizeof(inproc_fixture_data));
+  memset(&f, 0, sizeof(f));
+
+  f.fixture_data = ffd;
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
+
+  return f;
+}
+
+void inproc_init_client(grpc_end2end_test_fixture *f,
+                        grpc_channel_args *client_args) {
+  f->client = grpc_inproc_channel_create(f->server, client_args, NULL);
+  GPR_ASSERT(f->client);
+}
+
+void inproc_init_server(grpc_end2end_test_fixture *f,
+                        grpc_channel_args *server_args) {
+  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);
+  grpc_server_start(f->server);
+}
+
+void inproc_tear_down(grpc_end2end_test_fixture *f) {
+  inproc_fixture_data *ffd = f->fixture_data;
+  gpr_free(ffd);
+}
+
+/* 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},
+};
+
+int main(int argc, char **argv) {
+  size_t i;
+
+  grpc_test_init(argc, argv);
+  grpc_end2end_tests_pre_init();
+  grpc_init();
+
+  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
+    grpc_end2end_tests(argc, argv, configs[i]);
+  }
+
+  grpc_shutdown();
+
+  return 0;
+}
diff --git a/test/core/end2end/fuzzers/BUILD b/test/core/end2end/fuzzers/BUILD
index a9583d6..bf3a62a 100644
--- a/test/core/end2end/fuzzers/BUILD
+++ b/test/core/end2end/fuzzers/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 281a1af..01fa4f7 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -34,6 +34,7 @@
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/iomgr/timer_manager.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/support/env.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/metadata.h"
 #include "test/core/end2end/data/ssl_test_data.h"
@@ -731,7 +732,9 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   grpc_test_only_set_slice_hash_seed(0);
-  if (squelch) gpr_set_log_function(dont_log);
+  char *grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER");
+  if (squelch && grpc_trace_fuzzer == NULL) gpr_set_log_function(dont_log);
+  gpr_free(grpc_trace_fuzzer);
   input_stream inp = {data, data + size};
   grpc_tcp_client_connect_impl = my_tcp_client_connect;
   gpr_now_impl = now_impl;
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984
new file mode 100644
index 0000000..a5b7303
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 3ddc1ae..ef4c0a4 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -72,8 +72,9 @@
   grpc_metadata_array_init(&request_metadata1);
   int requested_calls = 0;
 
-  grpc_server_request_call(server, &call1, &call_details1, &request_metadata1,
-                           cq, cq, tag(1));
+  GPR_ASSERT(GRPC_CALL_OK ==
+             grpc_server_request_call(server, &call1, &call_details1,
+                                      &request_metadata1, cq, cq, tag(1)));
   requested_calls++;
 
   grpc_event ev;
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 6dffacf..18bae63 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -24,15 +24,15 @@
 
 FixtureOptions = collections.namedtuple(
     'FixtureOptions',
-    'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression')
+    'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth')
 default_unsecure_fixture_options = FixtureOptions(
-    True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False)
+    True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False)
 socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False)
 default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True)
 uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv'])
 fd_unsecure_fixture_options = default_unsecure_fixture_options._replace(
     dns_resolver=False, fullstack=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv'])
-
+inproc_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, fullstack=False, name_resolution=False, supports_compression=False, is_inproc=True, is_http2=False)
 
 # maps fixture name to whether it requires the security library
 END2END_FIXTURES = {
@@ -47,7 +47,7 @@
     'h2_full+trace': default_unsecure_fixture_options._replace(tracing=True),
     'h2_full+workarounds': default_unsecure_fixture_options,
     'h2_http_proxy': default_unsecure_fixture_options._replace(
-        ci_mac=False, exclude_iomgrs=['uv']),
+        ci_mac=False, exclude_iomgrs=['uv'], supports_proxy_auth=True),
     'h2_oauth2': default_secure_fixture_options._replace(
         ci_mac=False, exclude_iomgrs=['uv']),
     'h2_proxy': default_unsecure_fixture_options._replace(
@@ -64,12 +64,13 @@
     'h2_ssl_proxy': default_secure_fixture_options._replace(
         includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']),
     'h2_uds': uds_fixture_options,
+    'inproc': inproc_fixture_options
 }
 
 TestOptions = collections.namedtuple(
     'TestOptions',
-    'needs_fullstack needs_dns proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allow_compression')
-default_test_options = TestOptions(False, False, True, False, True, 1.0, [], False, False, True)
+    'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth')
+default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False)
 connectivity_test_options = default_test_options._replace(needs_fullstack=True)
 
 LOWCPU = 0.1
@@ -77,12 +78,12 @@
 # maps test names to options
 END2END_TESTS = {
     'authority_not_supported': default_test_options,
-    'bad_hostname': default_test_options,
+    'bad_hostname': default_test_options._replace(needs_names=True),
     'bad_ping': connectivity_test_options._replace(proxyable=False),
     'binary_metadata': default_test_options._replace(cpu_cost=LOWCPU),
     'resource_quota_server': default_test_options._replace(large_writes=True,
                                                            proxyable=False,
-                                                           allow_compression=False),
+                                                           allows_compression=False),
     'call_creds': default_test_options._replace(secure=True),
     'cancel_after_accept': default_test_options._replace(cpu_cost=LOWCPU),
     'cancel_after_client_done': default_test_options._replace(cpu_cost=LOWCPU),
@@ -91,17 +92,17 @@
     'cancel_before_invoke': default_test_options._replace(cpu_cost=LOWCPU),
     'cancel_in_a_vacuum': default_test_options._replace(cpu_cost=LOWCPU),
     'cancel_with_status': default_test_options._replace(cpu_cost=LOWCPU),
-    'compressed_payload': default_test_options._replace(proxyable=False),
-    'connectivity': connectivity_test_options._replace(
+    'compressed_payload': default_test_options._replace(proxyable=False,needs_compression=True),
+    'connectivity': connectivity_test_options._replace(needs_names=True,
         proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
     'default_host': default_test_options._replace(needs_fullstack=True,
-                                                  needs_dns=True),
-    'disappearing_server': connectivity_test_options._replace(flaky=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),
     'filter_causes_close': default_test_options._replace(cpu_cost=LOWCPU),
     'filter_call_init_fails': default_test_options,
     'filter_latency': default_test_options._replace(cpu_cost=LOWCPU),
-    'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU),
+    'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU,exclude_inproc=True),
     'hpack_size': default_test_options._replace(proxyable=False,
                                                 traceable=False,
                                                 cpu_cost=LOWCPU),
@@ -109,11 +110,13 @@
     'idempotent_request': default_test_options,
     'invoke_large_request': default_test_options,
     'keepalive_timeout': default_test_options._replace(proxyable=False,
-                                                       cpu_cost=LOWCPU),
+                                                       cpu_cost=LOWCPU,
+                                                       needs_http2=True),
     'large_metadata': default_test_options,
     'max_concurrent_streams': default_test_options._replace(
-        proxyable=False, cpu_cost=LOWCPU),
-    'max_connection_age': default_test_options._replace(cpu_cost=LOWCPU),
+        proxyable=False, cpu_cost=LOWCPU, exclude_inproc=True),
+    'max_connection_age': default_test_options._replace(cpu_cost=LOWCPU,
+                                                        exclude_inproc=True),
     'max_connection_idle': connectivity_test_options._replace(
         proxyable=False, exclude_iomgrs=['uv'], cpu_cost=LOWCPU),
     'max_message_length': default_test_options._replace(cpu_cost=LOWCPU),
@@ -125,6 +128,7 @@
     'load_reporting_hook': default_test_options,
     'ping_pong_streaming': default_test_options._replace(cpu_cost=LOWCPU),
     'ping': connectivity_test_options._replace(proxyable=False, cpu_cost=LOWCPU),
+    'proxy_auth': default_test_options._replace(needs_proxy_auth=True),
     'registered_call': default_test_options,
     'request_with_flags': default_test_options._replace(
         proxyable=False, cpu_cost=LOWCPU),
@@ -151,6 +155,9 @@
   if END2END_TESTS[t].needs_dns:
     if not END2END_FIXTURES[f].dns_resolver:
       return False
+  if END2END_TESTS[t].needs_names:
+    if not END2END_FIXTURES[f].name_resolution:
+      return False
   if not END2END_TESTS[t].proxyable:
     if END2END_FIXTURES[f].includes_proxy:
       return False
@@ -160,9 +167,21 @@
   if END2END_TESTS[t].large_writes:
     if not END2END_FIXTURES[f].large_writes:
       return False
-  if not END2END_TESTS[t].allow_compression:
+  if not END2END_TESTS[t].allows_compression:
     if END2END_FIXTURES[f].enables_compression:
       return False
+  if END2END_TESTS[t].needs_compression:
+    if not END2END_FIXTURES[f].supports_compression:
+      return False
+  if END2END_TESTS[t].exclude_inproc:
+    if END2END_FIXTURES[f].is_inproc:
+      return False
+  if END2END_TESTS[t].needs_http2:
+    if not END2END_FIXTURES[f].is_http2:
+      return False
+  if END2END_TESTS[t].needs_proxy_auth:
+    if not END2END_FIXTURES[f].supports_proxy_auth:
+      return False
   return True
 
 
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 3312f4e..6d1917c 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -19,14 +19,19 @@
 
 
 def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True,
-                    secure=True, tracing=False,
-                    platforms=['windows', 'linux', 'mac', 'posix']):
+                    name_resolution=True, secure=True, tracing=False,
+                    platforms=['windows', 'linux', 'mac', 'posix'],
+                    is_inproc=False, is_http2=True, supports_proxy_auth=False):
   return struct(
     fullstack=fullstack,
     includes_proxy=includes_proxy,
     dns_resolver=dns_resolver,
+    name_resolution=name_resolution,
     secure=secure,
     tracing=tracing,
+    is_inproc=is_inproc,
+    is_http2=is_http2,
+    supports_proxy_auth=supports_proxy_auth
     #platforms=platforms
   )
 
@@ -43,7 +48,7 @@
     'h2_full+pipe': fixture_options(platforms=['linux']),
     'h2_full+trace': fixture_options(tracing=True),
     'h2_full+workarounds': fixture_options(),
-    'h2_http_proxy': fixture_options(),
+    'h2_http_proxy': fixture_options(supports_proxy_auth=True),
     'h2_oauth2': fixture_options(),
     'h2_proxy': fixture_options(includes_proxy=True),
     'h2_sockpair_1byte': fixture_options(fullstack=False, dns_resolver=False),
@@ -55,24 +60,33 @@
     'h2_ssl_proxy': fixture_options(includes_proxy=True, secure=True),
     'h2_uds': fixture_options(dns_resolver=False,
                               platforms=['linux', 'mac', 'posix']),
+    'inproc': fixture_options(fullstack=False, dns_resolver=False,
+                              name_resolution=False, is_inproc=True,
+                              is_http2=False),
 }
 
 
-def test_options(needs_fullstack=False, needs_dns=False, proxyable=True,
-                 secure=False, traceable=False):
+def test_options(needs_fullstack=False, needs_dns=False, needs_names=False,
+                 proxyable=True, secure=False, traceable=False,
+                 exclude_inproc=False, needs_http2=False,
+                 needs_proxy_auth=False):
   return struct(
     needs_fullstack=needs_fullstack,
     needs_dns=needs_dns,
+    needs_names=needs_names,
     proxyable=proxyable,
     secure=secure,
-    traceable=traceable
+    traceable=traceable,
+    exclude_inproc=exclude_inproc,
+    needs_http2=needs_http2,
+    needs_proxy_auth=needs_proxy_auth
   )
 
 
 # maps test names to options
 END2END_TESTS = {
-    'bad_hostname': test_options(),
-    'bad_ping': test_options(),
+    'bad_hostname': test_options(needs_names=True),
+    'bad_ping': test_options(needs_fullstack=True,proxyable=False),
     'binary_metadata': test_options(),
     'resource_quota_server': test_options(proxyable=False),
     'call_creds': test_options(secure=True),
@@ -83,22 +97,25 @@
     'cancel_before_invoke': test_options(),
     'cancel_in_a_vacuum': test_options(),
     'cancel_with_status': test_options(),
-    'compressed_payload': test_options(proxyable=False),
-    'connectivity': test_options(needs_fullstack=True, proxyable=False),
-    'default_host': test_options(needs_fullstack=True, needs_dns=True),
-    'disappearing_server': test_options(needs_fullstack=True),
+    'compressed_payload': test_options(proxyable=False, exclude_inproc=True),
+    'connectivity': test_options(needs_fullstack=True, needs_names=True,
+                                 proxyable=False),
+    'default_host': test_options(needs_fullstack=True, needs_dns=True,
+                                 needs_names=True),
+    'disappearing_server': test_options(needs_fullstack=True,needs_names=True),
     'empty_batch': test_options(),
     'filter_causes_close': test_options(),
     'filter_call_init_fails': test_options(),
-    'graceful_server_shutdown': test_options(),
-    'hpack_size': test_options(proxyable=False, traceable=False),
+    'graceful_server_shutdown': test_options(exclude_inproc=True),
+    'hpack_size': test_options(proxyable=False, traceable=False,
+                               exclude_inproc=True),
     'high_initial_seqno': test_options(),
     'idempotent_request': test_options(),
     'invoke_large_request': test_options(),
-    'keepalive_timeout': test_options(proxyable=False),
+    'keepalive_timeout': test_options(proxyable=False, needs_http2=True),
     'large_metadata': test_options(),
-    'max_concurrent_streams': test_options(proxyable=False),
-    'max_connection_age': test_options(),
+    'max_concurrent_streams': test_options(proxyable=False, exclude_inproc=True),
+    'max_connection_age': test_options(exclude_inproc=True),
     'max_connection_idle': test_options(needs_fullstack=True, proxyable=False),
     'max_message_length': test_options(),
     'negative_deadline': test_options(),
@@ -109,6 +126,7 @@
     'load_reporting_hook': test_options(),
     'ping_pong_streaming': test_options(),
     'ping': test_options(needs_fullstack=True, proxyable=False),
+    'proxy_auth': test_options(needs_proxy_auth=True),
     'registered_call': test_options(),
     'request_with_flags': test_options(proxyable=False),
     'request_with_payload': test_options(),
@@ -136,12 +154,24 @@
   if topt.needs_dns:
     if not fopt.dns_resolver:
       return False
+  if topt.needs_names:
+    if not fopt.name_resolution:
+      return False
   if not topt.proxyable:
     if fopt.includes_proxy:
       return False
   if not topt.traceable:
     if fopt.tracing:
       return False
+  if topt.exclude_inproc:
+    if fopt.is_inproc:
+      return False
+  if topt.needs_http2:
+    if not fopt.is_http2:
+      return False
+  if topt.needs_proxy_auth:
+    if not fopt.supports_proxy_auth:
+      return False
   return True
 
 
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index d659d11..fd26fd1 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -25,6 +25,7 @@
 #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 <grpc/support/useful.h>
 #include "src/core/lib/support/string.h"
@@ -138,7 +139,12 @@
   error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
 
-  grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL);
+  char *dynamic_string = gpr_strdup("xyz");
+  grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED,
+                               (const char *)dynamic_string, NULL);
+  // The API of \a description allows for it to be a dynamic/non-const
+  // string, test this guarantee.
+  gpr_free(dynamic_string);
 
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
diff --git a/test/core/end2end/tests/proxy_auth.c b/test/core/end2end/tests/proxy_auth.c
new file mode 100644
index 0000000..d922049
--- /dev/null
+++ b/test/core/end2end/tests/proxy_auth.c
@@ -0,0 +1,235 @@
+/*
+ *
+ * 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 test is for checking whether proxy authentication is working with HTTP
+ * Connect.
+ */
+#include "test/core/end2end/end2end_tests.h"
+#include "test/core/end2end/fixtures/http_proxy_fixture.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 <grpc/support/useful.h>
+#include "src/core/lib/support/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);
+  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(), NULL);
+  } 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),
+                                         NULL)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+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 simple_request_body(grpc_end2end_test_config config,
+                                grpc_end2end_test_fixture f) {
+  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, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
+      NULL);
+  GPR_ASSERT(c);
+
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != NULL);
+  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 = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  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 = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  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), 1);
+  cq_verify(cqv);
+
+  peer = grpc_call_get_peer(s);
+  GPR_ASSERT(peer != NULL);
+  gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+  gpr_free(peer);
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != NULL);
+  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 = NULL;
+  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 = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  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(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_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+}
+
+static void test_invoke_proxy_auth(grpc_end2end_test_config config) {
+  /* Indicate that the proxy requires user auth */
+  grpc_arg client_arg = {.type = GRPC_ARG_STRING,
+                         .key = GRPC_ARG_HTTP_PROXY_AUTH_CREDS,
+                         .value.string = GRPC_TEST_HTTP_PROXY_AUTH_CREDS};
+  grpc_channel_args client_args = {.num_args = 1, .args = &client_arg};
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_proxy_auth", &client_args, NULL);
+  simple_request_body(config, f);
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void proxy_auth(grpc_end2end_test_config config) {
+  test_invoke_proxy_auth(config);
+}
+
+void proxy_auth_pre_init(void) {}
diff --git a/test/core/fling/BUILD b/test/core/fling/BUILD
index 39e132f..b0d34e9 100644
--- a/test/core/fling/BUILD
+++ b/test/core/fling/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_cc_binary(
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 0f0f22f..b3a7fa2 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -77,8 +77,10 @@
 
 static void request_call(void) {
   grpc_metadata_array_init(&request_metadata_recv);
-  grpc_server_request_call(server, &call, &call_details, &request_metadata_recv,
-                           cq, cq, tag(FLING_SERVER_NEW_REQUEST));
+  GPR_ASSERT(GRPC_CALL_OK ==
+             grpc_server_request_call(server, &call, &call_details,
+                                      &request_metadata_recv, cq, cq,
+                                      tag(FLING_SERVER_NEW_REQUEST)));
 }
 
 static void handle_unary_method(void) {
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index 1c1a8f6..c93ddc8 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "client_ssl",
     srcs = ["client_ssl.c"],
diff --git a/test/core/http/BUILD b/test/core/http/BUILD
index 85f1c18..2831308 100644
--- a/test/core/http/BUILD
+++ b/test/core/http/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index 806c647..3e6fd37 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -18,7 +18,13 @@
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
-package(default_visibility = ["//visibility:public"]) # Useful for third party devs to test their io manager implementation.
+package(
+    default_visibility = ["//visibility:public"], # Useful for third party devs to test their io manager implementation.
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 grpc_cc_library(
     name = "endpoint_tests",
diff --git a/test/core/iomgr/ev_epollsig_linux_test.c b/test/core/iomgr/ev_epollsig_linux_test.c
index 1d272fa..c702065 100644
--- a/test/core/iomgr/ev_epollsig_linux_test.c
+++ b/test/core/iomgr/ev_epollsig_linux_test.c
@@ -79,7 +79,8 @@
                      GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_fd_cleanup"));
     grpc_exec_ctx_flush(exec_ctx);
 
-    grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
+    grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd,
+                   false /* already_closed */, "test_fd_cleanup");
     grpc_exec_ctx_flush(exec_ctx);
 
     GPR_ASSERT(release_fd == tfds[i].inner_fd);
@@ -294,7 +295,8 @@
   {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     grpc_fd_shutdown(&exec_ctx, shared.wakeup_desc, GRPC_ERROR_CANCELLED);
-    grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL, "done");
+    grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL,
+                   false /* already_closed */, "done");
     grpc_pollset_shutdown(&exec_ctx, shared.pollset,
                           GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset,
                                               grpc_schedule_on_exec_ctx));
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index 0259645..85d5d9c 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -114,7 +114,8 @@
                                 bool success) {
   session *se = arg;
   server *sv = se->sv;
-  grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, "a");
+  grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, false /* already_closed */,
+                 "a");
   gpr_free(se);
   /* Start to shutdown listen fd. */
   grpc_fd_shutdown(exec_ctx, sv->em_fd,
@@ -171,7 +172,8 @@
                                int success) {
   server *sv = arg;
 
-  grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, "b");
+  grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, false /* already_closed */,
+                 "b");
 
   gpr_mu_lock(g_mu);
   sv->done = 1;
@@ -291,7 +293,8 @@
 static void client_session_shutdown_cb(grpc_exec_ctx *exec_ctx,
                                        void *arg /*client */, int success) {
   client *cl = arg;
-  grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, "c");
+  grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, false /* already_closed */,
+                 "c");
   cl->done = 1;
   GPR_ASSERT(
       GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
@@ -511,7 +514,7 @@
   GPR_ASSERT(b.cb_that_ran == second_read_callback);
   gpr_mu_unlock(g_mu);
 
-  grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, "d");
+  grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, false /* already_closed */, "d");
   grpc_exec_ctx_finish(&exec_ctx);
   destroy_change_data(&a);
   destroy_change_data(&b);
diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c
index 6aedaf1..5750ac0 100644
--- a/test/core/iomgr/pollset_set_test.c
+++ b/test/core/iomgr/pollset_set_test.c
@@ -137,7 +137,8 @@
      * grpc_wakeup_fd and we would like to destroy it ourselves (by calling
      * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the
      * underlying fd, call it with a non-NULL 'release_fd' parameter */
-    grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
+    grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd,
+                   false /* already_closed */, "test_fd_cleanup");
     grpc_exec_ctx_flush(exec_ctx);
 
     grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd);
diff --git a/test/core/json/BUILD b/test/core/json/BUILD
index 764d9bf..36b0897 100644
--- a/test/core/json/BUILD
+++ b/test/core/json/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/nanopb/BUILD b/test/core/nanopb/BUILD
index d602a7d..bdb4688 100644
--- a/test/core/nanopb/BUILD
+++ b/test/core/nanopb/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD
index daef680..cee23ec 100644
--- a/test/core/network_benchmarks/BUILD
+++ b/test/core/network_benchmarks/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_binary(
     name = "low_level_ping_pong",
     srcs = ["low_level_ping_pong.c"],
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index 96127e1..241ffc0 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 9d419c7..e60e398 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -105,8 +105,6 @@
     " \"expires_in\":3599, "
     " \"token_type\":\"Bearer\"}";
 
-static const char test_user_data[] = "user data";
-
 static const char test_scope[] = "perm1 perm2";
 
 static const char test_signed_jwt[] =
@@ -134,11 +132,6 @@
   return result;
 }
 
-typedef struct {
-  const char *key;
-  const char *value;
-} expected_md;
-
 static grpc_httpcli_response http_response(int status, const char *body) {
   grpc_httpcli_response response;
   memset(&response, 0, sizeof(grpc_httpcli_response));
@@ -150,89 +143,57 @@
 
 /* -- Tests. -- */
 
-static void test_empty_md_store(void) {
+static void test_empty_md_array(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
-  GPR_ASSERT(store->num_entries == 0);
-  GPR_ASSERT(store->allocated == 0);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
+  grpc_credentials_mdelem_array md_array;
+  memset(&md_array, 0, sizeof(md_array));
+  GPR_ASSERT(md_array.md == NULL);
+  GPR_ASSERT(md_array.size == 0);
+  grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void test_ref_unref_empty_md_store(void) {
+static void test_add_to_empty_md_array(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
-  grpc_credentials_md_store_ref(store);
-  grpc_credentials_md_store_ref(store);
-  GPR_ASSERT(store->num_entries == 0);
-  GPR_ASSERT(store->allocated == 0);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
+  grpc_credentials_mdelem_array md_array;
+  memset(&md_array, 0, sizeof(md_array));
+  const char *key = "hello";
+  const char *value = "there blah blah blah blah blah blah blah";
+  grpc_mdelem md =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                              grpc_slice_from_copied_string(value));
+  grpc_credentials_mdelem_array_add(&md_array, md);
+  GPR_ASSERT(md_array.size == 1);
+  GPR_ASSERT(grpc_mdelem_eq(md, md_array.md[0]));
+  GRPC_MDELEM_UNREF(&exec_ctx, md);
+  grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void test_add_to_empty_md_store(void) {
+static void test_add_abunch_to_md_array(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
-  const char *key_str = "hello";
-  const char *value_str = "there blah blah blah blah blah blah blah";
-  grpc_slice key = grpc_slice_from_copied_string(key_str);
-  grpc_slice value = grpc_slice_from_copied_string(value_str);
-  grpc_credentials_md_store_add(store, key, value);
-  GPR_ASSERT(store->num_entries == 1);
-  GPR_ASSERT(grpc_slice_eq(key, store->entries[0].key));
-  GPR_ASSERT(grpc_slice_eq(value, store->entries[0].value));
-  grpc_slice_unref(key);
-  grpc_slice_unref(value);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void test_add_cstrings_to_empty_md_store(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
-  const char *key_str = "hello";
-  const char *value_str = "there blah blah blah blah blah blah blah";
-  grpc_credentials_md_store_add_cstrings(store, key_str, value_str);
-  GPR_ASSERT(store->num_entries == 1);
-  GPR_ASSERT(grpc_slice_str_cmp(store->entries[0].key, key_str) == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(store->entries[0].value, value_str) == 0);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void test_empty_preallocated_md_store(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(4);
-  GPR_ASSERT(store->num_entries == 0);
-  GPR_ASSERT(store->allocated == 4);
-  GPR_ASSERT(store->entries != NULL);
-  grpc_credentials_md_store_unref(&exec_ctx, store);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void test_add_abunch_to_md_store(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *store = grpc_credentials_md_store_create(4);
+  grpc_credentials_mdelem_array md_array;
+  memset(&md_array, 0, sizeof(md_array));
+  const char *key = "hello";
+  const char *value = "there blah blah blah blah blah blah blah";
+  grpc_mdelem md =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                              grpc_slice_from_copied_string(value));
   size_t num_entries = 1000;
-  const char *key_str = "hello";
-  const char *value_str = "there blah blah blah blah blah blah blah";
-  size_t i;
-  for (i = 0; i < num_entries; i++) {
-    grpc_credentials_md_store_add_cstrings(store, key_str, value_str);
+  for (size_t i = 0; i < num_entries; ++i) {
+    grpc_credentials_mdelem_array_add(&md_array, md);
   }
-  for (i = 0; i < num_entries; i++) {
-    GPR_ASSERT(grpc_slice_str_cmp(store->entries[i].key, key_str) == 0);
-    GPR_ASSERT(grpc_slice_str_cmp(store->entries[i].value, value_str) == 0);
+  for (size_t i = 0; i < num_entries; ++i) {
+    GPR_ASSERT(grpc_mdelem_eq(md_array.md[i], md));
   }
-  grpc_credentials_md_store_unref(&exec_ctx, store);
+  GRPC_MDELEM_UNREF(&exec_ctx, md);
+  grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_ok(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response =
       http_response(200, valid_oauth2_json_response);
@@ -241,20 +202,18 @@
              GRPC_CREDENTIALS_OK);
   GPR_ASSERT(token_lifetime.tv_sec == 3599);
   GPR_ASSERT(token_lifetime.tv_nsec == 0);
-  GPR_ASSERT(token_md->num_entries == 1);
-  GPR_ASSERT(grpc_slice_str_cmp(token_md->entries[0].key, "authorization") ==
-             0);
-  GPR_ASSERT(grpc_slice_str_cmp(token_md->entries[0].value,
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(token_md), "authorization") == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(token_md),
                                 "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
              0);
-  grpc_credentials_md_store_unref(&exec_ctx, token_md);
+  GRPC_MDELEM_UNREF(&exec_ctx, token_md);
   grpc_http_response_destroy(&response);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response =
       http_response(401, valid_oauth2_json_response);
@@ -267,7 +226,7 @@
 
 static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response = http_response(200, "");
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
@@ -279,7 +238,7 @@
 
 static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response =
       http_response(200,
@@ -295,7 +254,7 @@
 
 static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response = http_response(200,
                                                  "{"
@@ -310,7 +269,7 @@
 
 static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response =
       http_response(200,
@@ -327,7 +286,7 @@
 static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
     void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials_md_store *token_md = NULL;
+  grpc_mdelem token_md = GRPC_MDNULL;
   gpr_timespec token_lifetime;
   grpc_httpcli_response response =
       http_response(200,
@@ -340,75 +299,121 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems,
-                           size_t num_md) {
-  size_t i;
-  for (i = 0; i < num_md; i++) {
+typedef struct {
+  const char *key;
+  const char *value;
+} expected_md;
+
+typedef struct {
+  grpc_error *expected_error;
+  const expected_md *expected;
+  size_t expected_size;
+  grpc_credentials_mdelem_array md_array;
+  grpc_closure on_request_metadata;
+  grpc_call_credentials *creds;
+} request_metadata_state;
+
+static void check_metadata(const expected_md *expected,
+                           grpc_credentials_mdelem_array *md_array) {
+  for (size_t i = 0; i < md_array->size; ++i) {
     size_t j;
-    for (j = 0; j < num_md; j++) {
-      if (0 == grpc_slice_str_cmp(md_elems[j].key, expected[i].key)) {
-        GPR_ASSERT(grpc_slice_str_cmp(md_elems[j].value, expected[i].value) ==
-                   0);
+    for (j = 0; j < md_array->size; ++j) {
+      if (0 ==
+          grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) {
+        GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]),
+                                      expected[i].value) == 0);
         break;
       }
     }
-    if (j == num_md) {
+    if (j == md_array->size) {
       gpr_log(GPR_ERROR, "key %s not found", expected[i].key);
       GPR_ASSERT(0);
     }
   }
 }
 
-static void check_google_iam_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
-                                      grpc_credentials_md *md_elems,
-                                      size_t num_md,
-                                      grpc_credentials_status status,
-                                      const char *error_details) {
-  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
-  expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
-                        test_google_iam_authorization_token},
-                       {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
-                        test_google_iam_authority_selector}};
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(error_details == NULL);
-  GPR_ASSERT(num_md == 2);
-  check_metadata(emd, md_elems, num_md);
-  grpc_call_credentials_unref(exec_ctx, c);
+static void check_request_metadata(grpc_exec_ctx *exec_ctx, void *arg,
+                                   grpc_error *error) {
+  request_metadata_state *state = (request_metadata_state *)arg;
+  gpr_log(GPR_INFO, "expected_error: %s",
+          grpc_error_string(state->expected_error));
+  gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error));
+  if (state->expected_error == GRPC_ERROR_NONE) {
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+  } else {
+    grpc_slice expected_error;
+    GPR_ASSERT(grpc_error_get_str(state->expected_error,
+                                  GRPC_ERROR_STR_DESCRIPTION, &expected_error));
+    grpc_slice actual_error;
+    GPR_ASSERT(
+        grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error));
+    GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0);
+    GRPC_ERROR_UNREF(state->expected_error);
+  }
+  gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR,
+          state->expected_size, state->md_array.size);
+  GPR_ASSERT(state->md_array.size == state->expected_size);
+  check_metadata(state->expected, &state->md_array);
+  grpc_credentials_mdelem_array_destroy(exec_ctx, &state->md_array);
+  gpr_free(state);
+}
+
+static request_metadata_state *make_request_metadata_state(
+    grpc_error *expected_error, const expected_md *expected,
+    size_t expected_size) {
+  request_metadata_state *state = gpr_zalloc(sizeof(*state));
+  state->expected_error = expected_error;
+  state->expected = expected;
+  state->expected_size = expected_size;
+  GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state,
+                    grpc_schedule_on_exec_ctx);
+  return state;
+}
+
+static void run_request_metadata_test(grpc_exec_ctx *exec_ctx,
+                                      grpc_call_credentials *creds,
+                                      grpc_auth_metadata_context auth_md_ctx,
+                                      request_metadata_state *state) {
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (grpc_call_credentials_get_request_metadata(
+          exec_ctx, creds, NULL, auth_md_ctx, &state->md_array,
+          &state->on_request_metadata, &error)) {
+    // Synchronous result.  Invoke the callback directly.
+    check_request_metadata(exec_ctx, state, error);
+    GRPC_ERROR_UNREF(error);
+  }
 }
 
 static void test_google_iam_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
+                        test_google_iam_authorization_token},
+                       {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
+                        test_google_iam_authority_selector}};
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_call_credentials *creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       NULL);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, auth_md_ctx, check_google_iam_metadata, creds);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void check_access_token_metadata(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
-  expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(error_details == NULL);
-  GPR_ASSERT(num_md == 1);
-  check_metadata(emd, md_elems, num_md);
-  grpc_call_credentials_unref(exec_ctx, c);
-}
-
 static void test_access_token_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_call_credentials *creds =
       grpc_access_token_credentials_create("blah", NULL);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
   GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata, creds);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -444,30 +449,20 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void check_oauth2_google_iam_composite_metadata(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
+static void test_oauth2_google_iam_composite_creds(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   expected_md emd[] = {
       {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
       {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
        test_google_iam_authorization_token},
       {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
        test_google_iam_authority_selector}};
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(error_details == NULL);
-  GPR_ASSERT(num_md == 3);
-  check_metadata(emd, md_elems, num_md);
-  grpc_call_credentials_unref(exec_ctx, c);
-}
-
-static void test_oauth2_google_iam_composite_creds(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  const grpc_call_credentials_array *creds_array;
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
   grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
-      "authorization", test_oauth2_bearer_token, 0);
+      &exec_ctx, "authorization", test_oauth2_bearer_token, 0);
   grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       NULL);
@@ -478,16 +473,15 @@
   grpc_call_credentials_unref(&exec_ctx, google_iam_creds);
   GPR_ASSERT(
       strcmp(composite_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
-  creds_array =
+  const grpc_call_credentials_array *creds_array =
       grpc_composite_call_credentials_get_credentials(composite_creds);
   GPR_ASSERT(creds_array->num_creds == 2);
   GPR_ASSERT(strcmp(creds_array->creds_array[0]->type,
                     GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
   GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
                     GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, composite_creds, NULL, auth_md_ctx,
-      check_oauth2_google_iam_composite_metadata, composite_creds);
+  run_request_metadata_test(&exec_ctx, composite_creds, auth_md_ctx, state);
+  grpc_call_credentials_unref(&exec_ctx, composite_creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -541,29 +535,6 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void on_oauth2_creds_get_metadata_success(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(error_details == NULL);
-  GPR_ASSERT(num_md == 1);
-  GPR_ASSERT(grpc_slice_str_cmp(md_elems[0].key, "authorization") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(md_elems[0].value,
-                                "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
-             0);
-  GPR_ASSERT(user_data != NULL);
-  GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
-}
-
-static void on_oauth2_creds_get_metadata_failure(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
-  GPR_ASSERT(num_md == 0);
-  GPR_ASSERT(user_data != NULL);
-  GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
-}
-
 static void validate_compute_engine_http_request(
     const grpc_httpcli_request *request) {
   GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl);
@@ -616,43 +587,48 @@
 
 static void test_compute_engine_creds_success(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_call_credentials *compute_engine_creds =
+  expected_md emd[] = {
+      {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
+  grpc_call_credentials *creds =
       grpc_google_compute_engine_credentials_create(NULL);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
 
   /* First request: http get should be called. */
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
   /* Second request: the cached token should be served directly. */
+  state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_success, (void *)test_user_data);
-  grpc_exec_ctx_finish(&exec_ctx);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
+  grpc_exec_ctx_flush(&exec_ctx);
 
-  grpc_call_credentials_unref(&exec_ctx, compute_engine_creds);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_httpcli_set_override(NULL, NULL);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_compute_engine_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  request_metadata_state *state = make_request_metadata_state(
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "Error occured when fetching oauth2 token."),
+      NULL, 0);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials *compute_engine_creds =
+  grpc_call_credentials *creds =
       grpc_google_compute_engine_credentials_create(NULL);
   grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
                             httpcli_post_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
-  grpc_call_credentials_unref(&exec_ctx, compute_engine_creds);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -702,46 +678,48 @@
 
 static void test_refresh_token_creds_success(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  expected_md emd[] = {
+      {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials *refresh_token_creds =
-      grpc_google_refresh_token_credentials_create(test_refresh_token_str,
-                                                   NULL);
+  grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create(
+      test_refresh_token_str, NULL);
 
   /* First request: http get should be called. */
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_success);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
   /* Second request: the cached token should be served directly. */
+  state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
-  grpc_call_credentials_unref(&exec_ctx, refresh_token_creds);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_refresh_token_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  request_metadata_state *state = make_request_metadata_state(
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "Error occured when fetching oauth2 token."),
+      NULL, 0);
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials *refresh_token_creds =
-      grpc_google_refresh_token_credentials_create(test_refresh_token_str,
-                                                   NULL);
+  grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create(
+      test_refresh_token_str, NULL);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_failure);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
-  grpc_call_credentials_unref(&exec_ctx, refresh_token_creds);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -792,28 +770,43 @@
   return NULL;
 }
 
-static void on_jwt_creds_get_metadata_success(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  char *expected_md_value;
-  gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(error_details == NULL);
-  GPR_ASSERT(num_md == 1);
-  GPR_ASSERT(grpc_slice_str_cmp(md_elems[0].key, "authorization") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(md_elems[0].value, expected_md_value) == 0);
-  GPR_ASSERT(user_data != NULL);
-  GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
-  gpr_free(expected_md_value);
+static grpc_service_account_jwt_access_credentials *creds_as_jwt(
+    grpc_call_credentials *creds) {
+  GPR_ASSERT(creds != NULL);
+  GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0);
+  return (grpc_service_account_jwt_access_credentials *)creds;
 }
 
-static void on_jwt_creds_get_metadata_failure(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
-  GPR_ASSERT(num_md == 0);
-  GPR_ASSERT(user_data != NULL);
-  GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
+static void test_jwt_creds_lifetime(void) {
+  char *json_key_string = test_json_key_str();
+
+  // Max lifetime.
+  grpc_call_credentials *jwt_creds =
+      grpc_service_account_jwt_access_credentials_create(
+          json_key_string, grpc_max_auth_token_lifetime(), NULL);
+  GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime,
+                          grpc_max_auth_token_lifetime()) == 0);
+  grpc_call_credentials_release(jwt_creds);
+
+  // Shorter lifetime.
+  gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN};
+  GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0);
+  jwt_creds = grpc_service_account_jwt_access_credentials_create(
+      json_key_string, token_lifetime, NULL);
+  GPR_ASSERT(
+      gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, token_lifetime) == 0);
+  grpc_call_credentials_release(jwt_creds);
+
+  // Cropped lifetime.
+  gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN};
+  token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max);
+  jwt_creds = grpc_service_account_jwt_access_credentials_create(
+      json_key_string, token_lifetime, NULL);
+  GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime,
+                          grpc_max_auth_token_lifetime()) == 0);
+  grpc_call_credentials_release(jwt_creds);
+
+  gpr_free(json_key_string);
 }
 
 static void test_jwt_creds_success(void) {
@@ -821,37 +814,42 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials *jwt_creds =
+  char *expected_md_value;
+  gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
+  expected_md emd[] = {{"authorization", expected_md_value}};
+  grpc_call_credentials *creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime(), NULL);
 
   /* First request: jwt_encode_and_sign should be called. */
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
-      on_jwt_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
   /* Second request: the cached token should be served directly. */
+  state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_jwt_encode_and_sign_set_override(
       encode_and_sign_jwt_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
-      on_jwt_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
   /* Third request: Different service url so jwt_encode_and_sign should be
      called again (no caching). */
+  state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   auth_md_ctx.service_url = other_test_service_url;
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
-      on_jwt_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
 
+  grpc_call_credentials_unref(&exec_ctx, creds);
   gpr_free(json_key_string);
-  grpc_call_credentials_unref(&exec_ctx, jwt_creds);
+  gpr_free(expected_md_value);
   grpc_jwt_encode_and_sign_set_override(NULL);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_jwt_creds_signing_failure(void) {
@@ -859,17 +857,17 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
-  grpc_call_credentials *jwt_creds =
+  request_metadata_state *state = make_request_metadata_state(
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), NULL, 0);
+  grpc_call_credentials *creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime(), NULL);
 
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, jwt_creds, NULL, auth_md_ctx,
-      on_jwt_creds_get_metadata_failure, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state);
 
   gpr_free(json_key_string);
-  grpc_call_credentials_unref(&exec_ctx, jwt_creds);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_jwt_encode_and_sign_set_override(NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -947,8 +945,10 @@
 
 static void test_google_default_creds_gce(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_composite_channel_credentials *creds;
-  grpc_channel_credentials *cached_creds;
+  expected_md emd[] = {
+      {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
+  request_metadata_state *state =
+      make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
   grpc_flush_cached_google_default_credentials();
@@ -960,33 +960,33 @@
   grpc_httpcli_set_override(
       default_creds_gce_detection_httpcli_get_success_override,
       httpcli_post_should_not_be_called);
-  creds = (grpc_composite_channel_credentials *)
-      grpc_google_default_credentials_create();
+  grpc_composite_channel_credentials *creds =
+      (grpc_composite_channel_credentials *)
+          grpc_google_default_credentials_create();
 
   /* Verify that the default creds actually embeds a GCE creds. */
   GPR_ASSERT(creds != NULL);
   GPR_ASSERT(creds->call_creds != NULL);
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds->call_creds, NULL, auth_md_ctx,
-      on_oauth2_creds_get_metadata_success, (void *)test_user_data);
+  run_request_metadata_test(&exec_ctx, creds->call_creds, auth_md_ctx, state);
   grpc_exec_ctx_flush(&exec_ctx);
-  grpc_exec_ctx_finish(&exec_ctx);
 
   /* Check that we get a cached creds if we call
      grpc_google_default_credentials_create again.
      GCE detection should not occur anymore either. */
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  cached_creds = grpc_google_default_credentials_create();
+  grpc_channel_credentials *cached_creds =
+      grpc_google_default_credentials_create();
   GPR_ASSERT(cached_creds == &creds->base);
 
   /* Cleanup. */
-  grpc_channel_credentials_release(cached_creds);
-  grpc_channel_credentials_release(&creds->base);
+  grpc_channel_credentials_unref(&exec_ctx, cached_creds);
+  grpc_channel_credentials_unref(&exec_ctx, &creds->base);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_override_well_known_credentials_path_getter(NULL);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static int default_creds_gce_detection_httpcli_get_failure_override(
@@ -1029,12 +1029,7 @@
   PLUGIN_DESTROY_CALLED_STATE
 } plugin_state;
 
-typedef struct {
-  const char *key;
-  const char *value;
-} plugin_metadata;
-
-static const plugin_metadata plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
+static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
 
 static void plugin_get_metadata_success(void *state,
                                         grpc_auth_metadata_context context,
@@ -1071,79 +1066,60 @@
   cb(user_data, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, plugin_error_details);
 }
 
-static void on_plugin_metadata_received_success(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  size_t i = 0;
-  GPR_ASSERT(user_data == NULL);
-  GPR_ASSERT(md_elems != NULL);
-  GPR_ASSERT(num_md == GPR_ARRAY_SIZE(plugin_md));
-  for (i = 0; i < num_md; i++) {
-    GPR_ASSERT(grpc_slice_str_cmp(md_elems[i].key, plugin_md[i].key) == 0);
-    GPR_ASSERT(grpc_slice_str_cmp(md_elems[i].value, plugin_md[i].value) == 0);
-  }
-}
-
-static void on_plugin_metadata_received_failure(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status, const char *error_details) {
-  GPR_ASSERT(user_data == NULL);
-  GPR_ASSERT(md_elems == NULL);
-  GPR_ASSERT(num_md == 0);
-  GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
-  GPR_ASSERT(error_details != NULL);
-  GPR_ASSERT(strcmp(error_details, plugin_error_details) == 0);
-}
-
 static void plugin_destroy(void *state) {
   plugin_state *s = (plugin_state *)state;
   *s = PLUGIN_DESTROY_CALLED_STATE;
 }
 
 static void test_metadata_plugin_success(void) {
-  grpc_call_credentials *creds;
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
+  request_metadata_state *md_state = make_request_metadata_state(
+      GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md));
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_success;
   plugin.destroy = plugin_destroy;
 
-  creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
+  grpc_call_credentials *creds =
+      grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_success,
-      NULL);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
-  grpc_call_credentials_release(creds);
-  GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_exec_ctx_finish(&exec_ctx);
+  GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
 }
 
 static void test_metadata_plugin_failure(void) {
-  grpc_call_credentials *creds;
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
                                             NULL};
+  char *expected_error;
+  gpr_asprintf(&expected_error,
+               "Getting metadata from plugin failed with error: %s",
+               plugin_error_details);
+  request_metadata_state *md_state = make_request_metadata_state(
+      GRPC_ERROR_CREATE_FROM_COPIED_STRING(expected_error), NULL, 0);
+  gpr_free(expected_error);
 
   plugin.state = &state;
   plugin.get_metadata = plugin_get_metadata_failure;
   plugin.destroy = plugin_destroy;
 
-  creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
+  grpc_call_credentials *creds =
+      grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_failure,
-      NULL);
+  run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
-  grpc_call_credentials_release(creds);
-  GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
+  grpc_call_credentials_unref(&exec_ctx, creds);
   grpc_exec_ctx_finish(&exec_ctx);
+  GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
 }
 
 static void test_get_well_known_google_credentials_file_path(void) {
@@ -1194,12 +1170,9 @@
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
-  test_empty_md_store();
-  test_ref_unref_empty_md_store();
-  test_add_to_empty_md_store();
-  test_add_cstrings_to_empty_md_store();
-  test_empty_preallocated_md_store();
-  test_add_abunch_to_md_store();
+  test_empty_md_array();
+  test_add_to_empty_md_array();
+  test_add_abunch_to_md_array();
   test_oauth2_token_fetcher_creds_parsing_ok();
   test_oauth2_token_fetcher_creds_parsing_bad_http_status();
   test_oauth2_token_fetcher_creds_parsing_empty_http_body();
@@ -1216,6 +1189,7 @@
   test_compute_engine_creds_failure();
   test_refresh_token_creds_success();
   test_refresh_token_creds_failure();
+  test_jwt_creds_lifetime();
   test_jwt_creds_success();
   test_jwt_creds_signing_failure();
   test_google_default_creds_auth_key();
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index e2331fb..fdbc6ea 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -32,29 +32,31 @@
 typedef struct {
   gpr_mu *mu;
   grpc_polling_entity pops;
-  int is_done;
+  bool is_done;
   char *token;
+
+  grpc_credentials_mdelem_array md_array;
+  grpc_closure closure;
 } oauth2_request;
 
-static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *user_data,
-                               grpc_credentials_md *md_elems, size_t num_md,
-                               grpc_credentials_status status,
-                               const char *error_details) {
-  oauth2_request *request = (oauth2_request *)user_data;
+static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *arg,
+                               grpc_error *error) {
+  oauth2_request *request = (oauth2_request *)arg;
   char *token = NULL;
   grpc_slice token_slice;
-  if (status == GRPC_CREDENTIALS_ERROR) {
-    gpr_log(GPR_ERROR, "Fetching token failed.");
+  if (error != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Fetching token failed: %s", grpc_error_string(error));
   } else {
-    GPR_ASSERT(num_md == 1);
-    token_slice = md_elems[0].value;
+    GPR_ASSERT(request->md_array.size == 1);
+    token_slice = GRPC_MDVALUE(request->md_array.md[0]);
     token = (char *)gpr_malloc(GRPC_SLICE_LENGTH(token_slice) + 1);
     memcpy(token, GRPC_SLICE_START_PTR(token_slice),
            GRPC_SLICE_LENGTH(token_slice));
     token[GRPC_SLICE_LENGTH(token_slice)] = '\0';
   }
+  grpc_credentials_mdelem_array_destroy(exec_ctx, &request->md_array);
   gpr_mu_lock(request->mu);
-  request->is_done = 1;
+  request->is_done = true;
   request->token = token;
   GRPC_LOG_IF_ERROR(
       "pollset_kick",
@@ -68,6 +70,7 @@
 char *grpc_test_fetch_oauth2_token_with_credentials(
     grpc_call_credentials *creds) {
   oauth2_request request;
+  memset(&request, 0, sizeof(request));
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_closure do_nothing_closure;
   grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
@@ -75,15 +78,23 @@
   grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &request.mu);
   request.pops = grpc_polling_entity_create_from_pollset(pollset);
-  request.is_done = 0;
+  request.is_done = false;
 
   GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL,
                     grpc_schedule_on_exec_ctx);
 
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, creds, &request.pops, null_ctx, on_oauth2_response, &request);
+  GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request,
+                    grpc_schedule_on_exec_ctx);
 
-  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (grpc_call_credentials_get_request_metadata(
+          &exec_ctx, creds, &request.pops, null_ctx, &request.md_array,
+          &request.closure, &error)) {
+    // Synchronous result; invoke callback directly.
+    on_oauth2_response(&exec_ctx, &request, error);
+    GRPC_ERROR_UNREF(error);
+  }
+  grpc_exec_ctx_flush(&exec_ctx);
 
   gpr_mu_lock(request.mu);
   while (!request.is_done) {
@@ -94,7 +105,7 @@
                               grpc_polling_entity_pollset(&request.pops),
                               &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                               gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
-      request.is_done = 1;
+      request.is_done = true;
     }
   }
   gpr_mu_unlock(request.mu);
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 3c3d3a7..e1385a8 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -35,25 +35,26 @@
 typedef struct {
   gpr_mu *mu;
   grpc_polling_entity pops;
-  int is_done;
+  bool is_done;
+
+  grpc_credentials_mdelem_array md_array;
+  grpc_closure on_request_metadata;
 } synchronizer;
 
-static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *user_data,
-                                 grpc_credentials_md *md_elems, size_t num_md,
-                                 grpc_credentials_status status,
-                                 const char *error_details) {
-  synchronizer *sync = user_data;
-  if (status == GRPC_CREDENTIALS_ERROR) {
-    fprintf(stderr, "Fetching token failed.\n");
+static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *arg,
+                                 grpc_error *error) {
+  synchronizer *sync = arg;
+  if (error != GRPC_ERROR_NONE) {
+    fprintf(stderr, "Fetching token failed: %s\n", grpc_error_string(error));
   } else {
     char *token;
-    GPR_ASSERT(num_md == 1);
-    token = grpc_slice_to_c_string(md_elems[0].value);
+    GPR_ASSERT(sync->md_array.size == 1);
+    token = grpc_slice_to_c_string(GRPC_MDVALUE(sync->md_array.md[0]));
     printf("\nGot token: %s\n\n", token);
     gpr_free(token);
   }
   gpr_mu_lock(sync->mu);
-  sync->is_done = 1;
+  sync->is_done = true;
   GRPC_LOG_IF_ERROR(
       "pollset_kick",
       grpc_pollset_kick(grpc_polling_entity_pollset(&sync->pops), NULL));
@@ -83,14 +84,23 @@
     goto end;
   }
 
+  memset(&sync, 0, sizeof(sync));
   grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &sync.mu);
   sync.pops = grpc_polling_entity_create_from_pollset(pollset);
-  sync.is_done = 0;
+  sync.is_done = false;
+  GRPC_CLOSURE_INIT(&sync.on_request_metadata, on_metadata_response, &sync,
+                    grpc_schedule_on_exec_ctx);
 
-  grpc_call_credentials_get_request_metadata(
-      &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
-      &sync.pops, context, on_metadata_response, &sync);
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (grpc_call_credentials_get_request_metadata(
+          &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
+          &sync.pops, context, &sync.md_array, &sync.on_request_metadata,
+          &error)) {
+    // Synchronous response.  Invoke callback directly.
+    on_metadata_response(&exec_ctx, &sync, error);
+    GRPC_ERROR_UNREF(error);
+  }
 
   gpr_mu_lock(sync.mu);
   while (!sync.is_done) {
@@ -101,7 +111,7 @@
                               grpc_polling_entity_pollset(&sync.pops), &worker,
                               gpr_now(GPR_CLOCK_MONOTONIC),
                               gpr_inf_future(GPR_CLOCK_MONOTONIC))))
-      sync.is_done = 1;
+      sync.is_done = true;
     gpr_mu_unlock(sync.mu);
     grpc_exec_ctx_flush(&exec_ctx);
     gpr_mu_lock(sync.mu);
diff --git a/test/core/slice/BUILD b/test/core/slice/BUILD
index d8473b7..9f2225a 100644
--- a/test/core/slice/BUILD
+++ b/test/core/slice/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 37870d9..7e142c1 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "alloc_test",
     srcs = ["alloc_test.c"],
diff --git a/test/core/support/avl_test.c b/test/core/support/avl_test.c
index cd352d3..37424d6 100644
--- a/test/core/support/avl_test.c
+++ b/test/core/support/avl_test.c
@@ -33,29 +33,31 @@
   return b;
 }
 
-static long int_compare(void *int1, void *int2) {
+static long int_compare(void *int1, void *int2, void *unused) {
   return (*(int *)int1) - (*(int *)int2);
 }
-static void *int_copy(void *p) { return box(*(int *)p); }
+static void *int_copy(void *p, void *unused) { return box(*(int *)p); }
 
-static const gpr_avl_vtable int_int_vtable = {gpr_free, int_copy, int_compare,
-                                              gpr_free, int_copy};
+static void destroy(void *p, void *unused) { gpr_free(p); }
+
+static const gpr_avl_vtable int_int_vtable = {destroy, int_copy, int_compare,
+                                              destroy, int_copy};
 
 static void check_get(gpr_avl avl, int key, int value) {
   int *k = box(key);
-  GPR_ASSERT(*(int *)gpr_avl_get(avl, k) == value);
+  GPR_ASSERT(*(int *)gpr_avl_get(avl, k, NULL) == value);
   gpr_free(k);
 }
 
 static void check_negget(gpr_avl avl, int key) {
   int *k = box(key);
-  GPR_ASSERT(gpr_avl_get(avl, k) == NULL);
+  GPR_ASSERT(gpr_avl_get(avl, k, NULL) == NULL);
   gpr_free(k);
 }
 
 static gpr_avl remove_int(gpr_avl avl, int key) {
   int *k = box(key);
-  avl = gpr_avl_remove(avl, k);
+  avl = gpr_avl_remove(avl, k, NULL);
   gpr_free(k);
   return avl;
 }
@@ -64,94 +66,94 @@
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_get");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(1), box(11));
-  avl = gpr_avl_add(avl, box(2), box(22));
-  avl = gpr_avl_add(avl, box(3), box(33));
+  avl = gpr_avl_add(avl, box(1), box(11), NULL);
+  avl = gpr_avl_add(avl, box(2), box(22), NULL);
+  avl = gpr_avl_add(avl, box(3), box(33), NULL);
   check_get(avl, 1, 11);
   check_get(avl, 2, 22);
   check_get(avl, 3, 33);
   check_negget(avl, 4);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_ll(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_ll");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(5), box(1));
-  avl = gpr_avl_add(avl, box(4), box(2));
-  avl = gpr_avl_add(avl, box(3), box(3));
+  avl = gpr_avl_add(avl, box(5), box(1), NULL);
+  avl = gpr_avl_add(avl, box(4), box(2), NULL);
+  avl = gpr_avl_add(avl, box(3), box(3), NULL);
   GPR_ASSERT(*(int *)avl.root->key == 4);
   GPR_ASSERT(*(int *)avl.root->left->key == 3);
   GPR_ASSERT(*(int *)avl.root->right->key == 5);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_lr(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_lr");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(5), box(1));
-  avl = gpr_avl_add(avl, box(3), box(2));
-  avl = gpr_avl_add(avl, box(4), box(3));
+  avl = gpr_avl_add(avl, box(5), box(1), NULL);
+  avl = gpr_avl_add(avl, box(3), box(2), NULL);
+  avl = gpr_avl_add(avl, box(4), box(3), NULL);
   GPR_ASSERT(*(int *)avl.root->key == 4);
   GPR_ASSERT(*(int *)avl.root->left->key == 3);
   GPR_ASSERT(*(int *)avl.root->right->key == 5);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_rr(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_rr");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(3), box(1));
-  avl = gpr_avl_add(avl, box(4), box(2));
-  avl = gpr_avl_add(avl, box(5), box(3));
+  avl = gpr_avl_add(avl, box(3), box(1), NULL);
+  avl = gpr_avl_add(avl, box(4), box(2), NULL);
+  avl = gpr_avl_add(avl, box(5), box(3), NULL);
   GPR_ASSERT(*(int *)avl.root->key == 4);
   GPR_ASSERT(*(int *)avl.root->left->key == 3);
   GPR_ASSERT(*(int *)avl.root->right->key == 5);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_rl(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_rl");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(3), box(1));
-  avl = gpr_avl_add(avl, box(5), box(2));
-  avl = gpr_avl_add(avl, box(4), box(3));
+  avl = gpr_avl_add(avl, box(3), box(1), NULL);
+  avl = gpr_avl_add(avl, box(5), box(2), NULL);
+  avl = gpr_avl_add(avl, box(4), box(3), NULL);
   GPR_ASSERT(*(int *)avl.root->key == 4);
   GPR_ASSERT(*(int *)avl.root->left->key == 3);
   GPR_ASSERT(*(int *)avl.root->right->key == 5);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_unbalanced(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_unbalanced");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(5), box(1));
-  avl = gpr_avl_add(avl, box(4), box(2));
-  avl = gpr_avl_add(avl, box(3), box(3));
-  avl = gpr_avl_add(avl, box(2), box(4));
-  avl = gpr_avl_add(avl, box(1), box(5));
+  avl = gpr_avl_add(avl, box(5), box(1), NULL);
+  avl = gpr_avl_add(avl, box(4), box(2), NULL);
+  avl = gpr_avl_add(avl, box(3), box(3), NULL);
+  avl = gpr_avl_add(avl, box(2), box(4), NULL);
+  avl = gpr_avl_add(avl, box(1), box(5), NULL);
   GPR_ASSERT(*(int *)avl.root->key == 4);
   GPR_ASSERT(*(int *)avl.root->left->key == 2);
   GPR_ASSERT(*(int *)avl.root->left->left->key == 1);
   GPR_ASSERT(*(int *)avl.root->left->right->key == 3);
   GPR_ASSERT(*(int *)avl.root->right->key == 5);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_replace(void) {
   gpr_avl avl;
   gpr_log(GPR_DEBUG, "test_replace");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(1), box(1));
-  avl = gpr_avl_add(avl, box(1), box(2));
+  avl = gpr_avl_add(avl, box(1), box(1), NULL);
+  avl = gpr_avl_add(avl, box(1), box(2), NULL);
   check_get(avl, 1, 2);
   check_negget(avl, 2);
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_remove(void) {
@@ -159,36 +161,36 @@
   gpr_avl avl3, avl4, avl5, avln;
   gpr_log(GPR_DEBUG, "test_remove");
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(3), box(1));
-  avl = gpr_avl_add(avl, box(4), box(2));
-  avl = gpr_avl_add(avl, box(5), box(3));
+  avl = gpr_avl_add(avl, box(3), box(1), NULL);
+  avl = gpr_avl_add(avl, box(4), box(2), NULL);
+  avl = gpr_avl_add(avl, box(5), box(3), NULL);
 
-  avl3 = remove_int(gpr_avl_ref(avl), 3);
-  avl4 = remove_int(gpr_avl_ref(avl), 4);
-  avl5 = remove_int(gpr_avl_ref(avl), 5);
-  avln = remove_int(gpr_avl_ref(avl), 1);
+  avl3 = remove_int(gpr_avl_ref(avl, NULL), 3);
+  avl4 = remove_int(gpr_avl_ref(avl, NULL), 4);
+  avl5 = remove_int(gpr_avl_ref(avl, NULL), 5);
+  avln = remove_int(gpr_avl_ref(avl, NULL), 1);
 
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 
   check_negget(avl3, 3);
   check_get(avl3, 4, 2);
   check_get(avl3, 5, 3);
-  gpr_avl_unref(avl3);
+  gpr_avl_unref(avl3, NULL);
 
   check_get(avl4, 3, 1);
   check_negget(avl4, 4);
   check_get(avl4, 5, 3);
-  gpr_avl_unref(avl4);
+  gpr_avl_unref(avl4, NULL);
 
   check_get(avl5, 3, 1);
   check_get(avl5, 4, 2);
   check_negget(avl5, 5);
-  gpr_avl_unref(avl5);
+  gpr_avl_unref(avl5, NULL);
 
   check_get(avln, 3, 1);
   check_get(avln, 4, 2);
   check_get(avln, 5, 3);
-  gpr_avl_unref(avln);
+  gpr_avl_unref(avln, NULL);
 }
 
 static void test_badcase1(void) {
@@ -197,44 +199,44 @@
   gpr_log(GPR_DEBUG, "test_badcase1");
 
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(88), box(1));
+  avl = gpr_avl_add(avl, box(88), box(1), NULL);
   avl = remove_int(avl, 643);
   avl = remove_int(avl, 983);
-  avl = gpr_avl_add(avl, box(985), box(4));
-  avl = gpr_avl_add(avl, box(640), box(5));
-  avl = gpr_avl_add(avl, box(41), box(6));
-  avl = gpr_avl_add(avl, box(112), box(7));
-  avl = gpr_avl_add(avl, box(342), box(8));
+  avl = gpr_avl_add(avl, box(985), box(4), NULL);
+  avl = gpr_avl_add(avl, box(640), box(5), NULL);
+  avl = gpr_avl_add(avl, box(41), box(6), NULL);
+  avl = gpr_avl_add(avl, box(112), box(7), NULL);
+  avl = gpr_avl_add(avl, box(342), box(8), NULL);
   avl = remove_int(avl, 1013);
-  avl = gpr_avl_add(avl, box(434), box(10));
-  avl = gpr_avl_add(avl, box(520), box(11));
-  avl = gpr_avl_add(avl, box(231), box(12));
-  avl = gpr_avl_add(avl, box(852), box(13));
+  avl = gpr_avl_add(avl, box(434), box(10), NULL);
+  avl = gpr_avl_add(avl, box(520), box(11), NULL);
+  avl = gpr_avl_add(avl, box(231), box(12), NULL);
+  avl = gpr_avl_add(avl, box(852), box(13), NULL);
   avl = remove_int(avl, 461);
-  avl = gpr_avl_add(avl, box(108), box(15));
-  avl = gpr_avl_add(avl, box(806), box(16));
-  avl = gpr_avl_add(avl, box(827), box(17));
+  avl = gpr_avl_add(avl, box(108), box(15), NULL);
+  avl = gpr_avl_add(avl, box(806), box(16), NULL);
+  avl = gpr_avl_add(avl, box(827), box(17), NULL);
   avl = remove_int(avl, 796);
-  avl = gpr_avl_add(avl, box(340), box(19));
-  avl = gpr_avl_add(avl, box(498), box(20));
-  avl = gpr_avl_add(avl, box(203), box(21));
-  avl = gpr_avl_add(avl, box(751), box(22));
-  avl = gpr_avl_add(avl, box(150), box(23));
+  avl = gpr_avl_add(avl, box(340), box(19), NULL);
+  avl = gpr_avl_add(avl, box(498), box(20), NULL);
+  avl = gpr_avl_add(avl, box(203), box(21), NULL);
+  avl = gpr_avl_add(avl, box(751), box(22), NULL);
+  avl = gpr_avl_add(avl, box(150), box(23), NULL);
   avl = remove_int(avl, 237);
-  avl = gpr_avl_add(avl, box(830), box(25));
+  avl = gpr_avl_add(avl, box(830), box(25), NULL);
   avl = remove_int(avl, 1007);
   avl = remove_int(avl, 394);
-  avl = gpr_avl_add(avl, box(65), box(28));
+  avl = gpr_avl_add(avl, box(65), box(28), NULL);
   avl = remove_int(avl, 904);
   avl = remove_int(avl, 123);
-  avl = gpr_avl_add(avl, box(238), box(31));
-  avl = gpr_avl_add(avl, box(184), box(32));
+  avl = gpr_avl_add(avl, box(238), box(31), NULL);
+  avl = gpr_avl_add(avl, box(184), box(32), NULL);
   avl = remove_int(avl, 331);
-  avl = gpr_avl_add(avl, box(827), box(34));
+  avl = gpr_avl_add(avl, box(827), box(34), NULL);
 
   check_get(avl, 830, 25);
 
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_badcase2(void) {
@@ -243,254 +245,254 @@
   gpr_log(GPR_DEBUG, "test_badcase2");
 
   avl = gpr_avl_create(&int_int_vtable);
-  avl = gpr_avl_add(avl, box(288), box(1));
+  avl = gpr_avl_add(avl, box(288), box(1), NULL);
   avl = remove_int(avl, 415);
-  avl = gpr_avl_add(avl, box(953), box(3));
-  avl = gpr_avl_add(avl, box(101), box(4));
-  avl = gpr_avl_add(avl, box(516), box(5));
-  avl = gpr_avl_add(avl, box(547), box(6));
-  avl = gpr_avl_add(avl, box(467), box(7));
-  avl = gpr_avl_add(avl, box(793), box(8));
+  avl = gpr_avl_add(avl, box(953), box(3), NULL);
+  avl = gpr_avl_add(avl, box(101), box(4), NULL);
+  avl = gpr_avl_add(avl, box(516), box(5), NULL);
+  avl = gpr_avl_add(avl, box(547), box(6), NULL);
+  avl = gpr_avl_add(avl, box(467), box(7), NULL);
+  avl = gpr_avl_add(avl, box(793), box(8), NULL);
   avl = remove_int(avl, 190);
-  avl = gpr_avl_add(avl, box(687), box(10));
-  avl = gpr_avl_add(avl, box(242), box(11));
-  avl = gpr_avl_add(avl, box(142), box(12));
+  avl = gpr_avl_add(avl, box(687), box(10), NULL);
+  avl = gpr_avl_add(avl, box(242), box(11), NULL);
+  avl = gpr_avl_add(avl, box(142), box(12), NULL);
   avl = remove_int(avl, 705);
   avl = remove_int(avl, 578);
   avl = remove_int(avl, 767);
   avl = remove_int(avl, 183);
-  avl = gpr_avl_add(avl, box(950), box(17));
-  avl = gpr_avl_add(avl, box(622), box(18));
+  avl = gpr_avl_add(avl, box(950), box(17), NULL);
+  avl = gpr_avl_add(avl, box(622), box(18), NULL);
   avl = remove_int(avl, 513);
   avl = remove_int(avl, 429);
-  avl = gpr_avl_add(avl, box(205), box(21));
+  avl = gpr_avl_add(avl, box(205), box(21), NULL);
   avl = remove_int(avl, 663);
   avl = remove_int(avl, 953);
   avl = remove_int(avl, 892);
-  avl = gpr_avl_add(avl, box(236), box(25));
+  avl = gpr_avl_add(avl, box(236), box(25), NULL);
   avl = remove_int(avl, 982);
   avl = remove_int(avl, 201);
   avl = remove_int(avl, 684);
-  avl = gpr_avl_add(avl, box(572), box(29));
+  avl = gpr_avl_add(avl, box(572), box(29), NULL);
   avl = remove_int(avl, 817);
-  avl = gpr_avl_add(avl, box(970), box(31));
+  avl = gpr_avl_add(avl, box(970), box(31), NULL);
   avl = remove_int(avl, 347);
   avl = remove_int(avl, 574);
-  avl = gpr_avl_add(avl, box(752), box(34));
-  avl = gpr_avl_add(avl, box(670), box(35));
-  avl = gpr_avl_add(avl, box(69), box(36));
+  avl = gpr_avl_add(avl, box(752), box(34), NULL);
+  avl = gpr_avl_add(avl, box(670), box(35), NULL);
+  avl = gpr_avl_add(avl, box(69), box(36), NULL);
   avl = remove_int(avl, 111);
   avl = remove_int(avl, 523);
-  avl = gpr_avl_add(avl, box(141), box(39));
+  avl = gpr_avl_add(avl, box(141), box(39), NULL);
   avl = remove_int(avl, 159);
-  avl = gpr_avl_add(avl, box(947), box(41));
-  avl = gpr_avl_add(avl, box(855), box(42));
+  avl = gpr_avl_add(avl, box(947), box(41), NULL);
+  avl = gpr_avl_add(avl, box(855), box(42), NULL);
   avl = remove_int(avl, 218);
   avl = remove_int(avl, 6);
-  avl = gpr_avl_add(avl, box(753), box(45));
+  avl = gpr_avl_add(avl, box(753), box(45), NULL);
   avl = remove_int(avl, 82);
   avl = remove_int(avl, 799);
-  avl = gpr_avl_add(avl, box(572), box(48));
+  avl = gpr_avl_add(avl, box(572), box(48), NULL);
   avl = remove_int(avl, 376);
   avl = remove_int(avl, 413);
-  avl = gpr_avl_add(avl, box(458), box(51));
+  avl = gpr_avl_add(avl, box(458), box(51), NULL);
   avl = remove_int(avl, 897);
-  avl = gpr_avl_add(avl, box(191), box(53));
-  avl = gpr_avl_add(avl, box(609), box(54));
+  avl = gpr_avl_add(avl, box(191), box(53), NULL);
+  avl = gpr_avl_add(avl, box(609), box(54), NULL);
   avl = remove_int(avl, 787);
   avl = remove_int(avl, 710);
   avl = remove_int(avl, 886);
   avl = remove_int(avl, 835);
   avl = remove_int(avl, 33);
-  avl = gpr_avl_add(avl, box(871), box(60));
+  avl = gpr_avl_add(avl, box(871), box(60), NULL);
   avl = remove_int(avl, 641);
-  avl = gpr_avl_add(avl, box(462), box(62));
+  avl = gpr_avl_add(avl, box(462), box(62), NULL);
   avl = remove_int(avl, 359);
   avl = remove_int(avl, 767);
-  avl = gpr_avl_add(avl, box(310), box(65));
+  avl = gpr_avl_add(avl, box(310), box(65), NULL);
   avl = remove_int(avl, 757);
   avl = remove_int(avl, 639);
   avl = remove_int(avl, 314);
-  avl = gpr_avl_add(avl, box(2), box(69));
+  avl = gpr_avl_add(avl, box(2), box(69), NULL);
   avl = remove_int(avl, 138);
-  avl = gpr_avl_add(avl, box(669), box(71));
+  avl = gpr_avl_add(avl, box(669), box(71), NULL);
   avl = remove_int(avl, 477);
-  avl = gpr_avl_add(avl, box(366), box(73));
-  avl = gpr_avl_add(avl, box(612), box(74));
-  avl = gpr_avl_add(avl, box(106), box(75));
+  avl = gpr_avl_add(avl, box(366), box(73), NULL);
+  avl = gpr_avl_add(avl, box(612), box(74), NULL);
+  avl = gpr_avl_add(avl, box(106), box(75), NULL);
   avl = remove_int(avl, 161);
-  avl = gpr_avl_add(avl, box(388), box(77));
-  avl = gpr_avl_add(avl, box(141), box(78));
+  avl = gpr_avl_add(avl, box(388), box(77), NULL);
+  avl = gpr_avl_add(avl, box(141), box(78), NULL);
   avl = remove_int(avl, 633);
   avl = remove_int(avl, 459);
-  avl = gpr_avl_add(avl, box(40), box(81));
+  avl = gpr_avl_add(avl, box(40), box(81), NULL);
   avl = remove_int(avl, 689);
-  avl = gpr_avl_add(avl, box(823), box(83));
+  avl = gpr_avl_add(avl, box(823), box(83), NULL);
   avl = remove_int(avl, 485);
-  avl = gpr_avl_add(avl, box(903), box(85));
-  avl = gpr_avl_add(avl, box(592), box(86));
+  avl = gpr_avl_add(avl, box(903), box(85), NULL);
+  avl = gpr_avl_add(avl, box(592), box(86), NULL);
   avl = remove_int(avl, 448);
-  avl = gpr_avl_add(avl, box(56), box(88));
+  avl = gpr_avl_add(avl, box(56), box(88), NULL);
   avl = remove_int(avl, 333);
-  avl = gpr_avl_add(avl, box(189), box(90));
-  avl = gpr_avl_add(avl, box(103), box(91));
+  avl = gpr_avl_add(avl, box(189), box(90), NULL);
+  avl = gpr_avl_add(avl, box(103), box(91), NULL);
   avl = remove_int(avl, 164);
   avl = remove_int(avl, 974);
-  avl = gpr_avl_add(avl, box(215), box(94));
+  avl = gpr_avl_add(avl, box(215), box(94), NULL);
   avl = remove_int(avl, 189);
   avl = remove_int(avl, 504);
-  avl = gpr_avl_add(avl, box(868), box(97));
+  avl = gpr_avl_add(avl, box(868), box(97), NULL);
   avl = remove_int(avl, 909);
   avl = remove_int(avl, 148);
   avl = remove_int(avl, 469);
-  avl = gpr_avl_add(avl, box(994), box(101));
-  avl = gpr_avl_add(avl, box(576), box(102));
+  avl = gpr_avl_add(avl, box(994), box(101), NULL);
+  avl = gpr_avl_add(avl, box(576), box(102), NULL);
   avl = remove_int(avl, 82);
   avl = remove_int(avl, 209);
-  avl = gpr_avl_add(avl, box(276), box(105));
+  avl = gpr_avl_add(avl, box(276), box(105), NULL);
   avl = remove_int(avl, 856);
-  avl = gpr_avl_add(avl, box(750), box(107));
+  avl = gpr_avl_add(avl, box(750), box(107), NULL);
   avl = remove_int(avl, 871);
-  avl = gpr_avl_add(avl, box(301), box(109));
+  avl = gpr_avl_add(avl, box(301), box(109), NULL);
   avl = remove_int(avl, 260);
   avl = remove_int(avl, 737);
   avl = remove_int(avl, 719);
-  avl = gpr_avl_add(avl, box(933), box(113));
-  avl = gpr_avl_add(avl, box(225), box(114));
-  avl = gpr_avl_add(avl, box(975), box(115));
-  avl = gpr_avl_add(avl, box(86), box(116));
+  avl = gpr_avl_add(avl, box(933), box(113), NULL);
+  avl = gpr_avl_add(avl, box(225), box(114), NULL);
+  avl = gpr_avl_add(avl, box(975), box(115), NULL);
+  avl = gpr_avl_add(avl, box(86), box(116), NULL);
   avl = remove_int(avl, 732);
-  avl = gpr_avl_add(avl, box(340), box(118));
-  avl = gpr_avl_add(avl, box(271), box(119));
+  avl = gpr_avl_add(avl, box(340), box(118), NULL);
+  avl = gpr_avl_add(avl, box(271), box(119), NULL);
   avl = remove_int(avl, 206);
-  avl = gpr_avl_add(avl, box(949), box(121));
-  avl = gpr_avl_add(avl, box(927), box(122));
-  avl = gpr_avl_add(avl, box(34), box(123));
-  avl = gpr_avl_add(avl, box(351), box(124));
+  avl = gpr_avl_add(avl, box(949), box(121), NULL);
+  avl = gpr_avl_add(avl, box(927), box(122), NULL);
+  avl = gpr_avl_add(avl, box(34), box(123), NULL);
+  avl = gpr_avl_add(avl, box(351), box(124), NULL);
   avl = remove_int(avl, 836);
-  avl = gpr_avl_add(avl, box(825), box(126));
-  avl = gpr_avl_add(avl, box(352), box(127));
+  avl = gpr_avl_add(avl, box(825), box(126), NULL);
+  avl = gpr_avl_add(avl, box(352), box(127), NULL);
   avl = remove_int(avl, 107);
   avl = remove_int(avl, 101);
-  avl = gpr_avl_add(avl, box(320), box(130));
-  avl = gpr_avl_add(avl, box(3), box(131));
+  avl = gpr_avl_add(avl, box(320), box(130), NULL);
+  avl = gpr_avl_add(avl, box(3), box(131), NULL);
   avl = remove_int(avl, 998);
   avl = remove_int(avl, 44);
-  avl = gpr_avl_add(avl, box(525), box(134));
-  avl = gpr_avl_add(avl, box(864), box(135));
-  avl = gpr_avl_add(avl, box(863), box(136));
+  avl = gpr_avl_add(avl, box(525), box(134), NULL);
+  avl = gpr_avl_add(avl, box(864), box(135), NULL);
+  avl = gpr_avl_add(avl, box(863), box(136), NULL);
   avl = remove_int(avl, 770);
-  avl = gpr_avl_add(avl, box(440), box(138));
+  avl = gpr_avl_add(avl, box(440), box(138), NULL);
   avl = remove_int(avl, 516);
-  avl = gpr_avl_add(avl, box(116), box(140));
+  avl = gpr_avl_add(avl, box(116), box(140), NULL);
   avl = remove_int(avl, 380);
-  avl = gpr_avl_add(avl, box(878), box(142));
+  avl = gpr_avl_add(avl, box(878), box(142), NULL);
   avl = remove_int(avl, 439);
-  avl = gpr_avl_add(avl, box(994), box(144));
+  avl = gpr_avl_add(avl, box(994), box(144), NULL);
   avl = remove_int(avl, 294);
   avl = remove_int(avl, 593);
-  avl = gpr_avl_add(avl, box(696), box(147));
+  avl = gpr_avl_add(avl, box(696), box(147), NULL);
   avl = remove_int(avl, 8);
-  avl = gpr_avl_add(avl, box(881), box(149));
+  avl = gpr_avl_add(avl, box(881), box(149), NULL);
   avl = remove_int(avl, 32);
   avl = remove_int(avl, 242);
-  avl = gpr_avl_add(avl, box(487), box(152));
-  avl = gpr_avl_add(avl, box(637), box(153));
-  avl = gpr_avl_add(avl, box(793), box(154));
-  avl = gpr_avl_add(avl, box(696), box(155));
+  avl = gpr_avl_add(avl, box(487), box(152), NULL);
+  avl = gpr_avl_add(avl, box(637), box(153), NULL);
+  avl = gpr_avl_add(avl, box(793), box(154), NULL);
+  avl = gpr_avl_add(avl, box(696), box(155), NULL);
   avl = remove_int(avl, 458);
-  avl = gpr_avl_add(avl, box(828), box(157));
+  avl = gpr_avl_add(avl, box(828), box(157), NULL);
   avl = remove_int(avl, 784);
   avl = remove_int(avl, 274);
-  avl = gpr_avl_add(avl, box(783), box(160));
+  avl = gpr_avl_add(avl, box(783), box(160), NULL);
   avl = remove_int(avl, 21);
-  avl = gpr_avl_add(avl, box(866), box(162));
+  avl = gpr_avl_add(avl, box(866), box(162), NULL);
   avl = remove_int(avl, 919);
-  avl = gpr_avl_add(avl, box(435), box(164));
+  avl = gpr_avl_add(avl, box(435), box(164), NULL);
   avl = remove_int(avl, 385);
-  avl = gpr_avl_add(avl, box(475), box(166));
+  avl = gpr_avl_add(avl, box(475), box(166), NULL);
   avl = remove_int(avl, 339);
-  avl = gpr_avl_add(avl, box(615), box(168));
+  avl = gpr_avl_add(avl, box(615), box(168), NULL);
   avl = remove_int(avl, 866);
   avl = remove_int(avl, 82);
   avl = remove_int(avl, 271);
-  avl = gpr_avl_add(avl, box(590), box(172));
-  avl = gpr_avl_add(avl, box(852), box(173));
+  avl = gpr_avl_add(avl, box(590), box(172), NULL);
+  avl = gpr_avl_add(avl, box(852), box(173), NULL);
   avl = remove_int(avl, 318);
   avl = remove_int(avl, 82);
-  avl = gpr_avl_add(avl, box(672), box(176));
+  avl = gpr_avl_add(avl, box(672), box(176), NULL);
   avl = remove_int(avl, 430);
-  avl = gpr_avl_add(avl, box(821), box(178));
-  avl = gpr_avl_add(avl, box(365), box(179));
+  avl = gpr_avl_add(avl, box(821), box(178), NULL);
+  avl = gpr_avl_add(avl, box(365), box(179), NULL);
   avl = remove_int(avl, 78);
-  avl = gpr_avl_add(avl, box(700), box(181));
-  avl = gpr_avl_add(avl, box(353), box(182));
+  avl = gpr_avl_add(avl, box(700), box(181), NULL);
+  avl = gpr_avl_add(avl, box(353), box(182), NULL);
   avl = remove_int(avl, 492);
-  avl = gpr_avl_add(avl, box(991), box(184));
+  avl = gpr_avl_add(avl, box(991), box(184), NULL);
   avl = remove_int(avl, 330);
-  avl = gpr_avl_add(avl, box(873), box(186));
+  avl = gpr_avl_add(avl, box(873), box(186), NULL);
   avl = remove_int(avl, 589);
-  avl = gpr_avl_add(avl, box(676), box(188));
-  avl = gpr_avl_add(avl, box(790), box(189));
+  avl = gpr_avl_add(avl, box(676), box(188), NULL);
+  avl = gpr_avl_add(avl, box(790), box(189), NULL);
   avl = remove_int(avl, 521);
   avl = remove_int(avl, 47);
-  avl = gpr_avl_add(avl, box(976), box(192));
-  avl = gpr_avl_add(avl, box(683), box(193));
+  avl = gpr_avl_add(avl, box(976), box(192), NULL);
+  avl = gpr_avl_add(avl, box(683), box(193), NULL);
   avl = remove_int(avl, 803);
   avl = remove_int(avl, 1006);
-  avl = gpr_avl_add(avl, box(775), box(196));
-  avl = gpr_avl_add(avl, box(411), box(197));
-  avl = gpr_avl_add(avl, box(697), box(198));
+  avl = gpr_avl_add(avl, box(775), box(196), NULL);
+  avl = gpr_avl_add(avl, box(411), box(197), NULL);
+  avl = gpr_avl_add(avl, box(697), box(198), NULL);
   avl = remove_int(avl, 50);
-  avl = gpr_avl_add(avl, box(213), box(200));
+  avl = gpr_avl_add(avl, box(213), box(200), NULL);
   avl = remove_int(avl, 714);
-  avl = gpr_avl_add(avl, box(981), box(202));
-  avl = gpr_avl_add(avl, box(502), box(203));
-  avl = gpr_avl_add(avl, box(697), box(204));
-  avl = gpr_avl_add(avl, box(603), box(205));
-  avl = gpr_avl_add(avl, box(117), box(206));
+  avl = gpr_avl_add(avl, box(981), box(202), NULL);
+  avl = gpr_avl_add(avl, box(502), box(203), NULL);
+  avl = gpr_avl_add(avl, box(697), box(204), NULL);
+  avl = gpr_avl_add(avl, box(603), box(205), NULL);
+  avl = gpr_avl_add(avl, box(117), box(206), NULL);
   avl = remove_int(avl, 363);
-  avl = gpr_avl_add(avl, box(104), box(208));
+  avl = gpr_avl_add(avl, box(104), box(208), NULL);
   avl = remove_int(avl, 842);
-  avl = gpr_avl_add(avl, box(48), box(210));
+  avl = gpr_avl_add(avl, box(48), box(210), NULL);
   avl = remove_int(avl, 764);
-  avl = gpr_avl_add(avl, box(482), box(212));
-  avl = gpr_avl_add(avl, box(928), box(213));
-  avl = gpr_avl_add(avl, box(30), box(214));
-  avl = gpr_avl_add(avl, box(820), box(215));
-  avl = gpr_avl_add(avl, box(334), box(216));
+  avl = gpr_avl_add(avl, box(482), box(212), NULL);
+  avl = gpr_avl_add(avl, box(928), box(213), NULL);
+  avl = gpr_avl_add(avl, box(30), box(214), NULL);
+  avl = gpr_avl_add(avl, box(820), box(215), NULL);
+  avl = gpr_avl_add(avl, box(334), box(216), NULL);
   avl = remove_int(avl, 306);
-  avl = gpr_avl_add(avl, box(789), box(218));
+  avl = gpr_avl_add(avl, box(789), box(218), NULL);
   avl = remove_int(avl, 924);
-  avl = gpr_avl_add(avl, box(53), box(220));
+  avl = gpr_avl_add(avl, box(53), box(220), NULL);
   avl = remove_int(avl, 657);
-  avl = gpr_avl_add(avl, box(130), box(222));
-  avl = gpr_avl_add(avl, box(239), box(223));
+  avl = gpr_avl_add(avl, box(130), box(222), NULL);
+  avl = gpr_avl_add(avl, box(239), box(223), NULL);
   avl = remove_int(avl, 20);
-  avl = gpr_avl_add(avl, box(117), box(225));
+  avl = gpr_avl_add(avl, box(117), box(225), NULL);
   avl = remove_int(avl, 882);
   avl = remove_int(avl, 891);
-  avl = gpr_avl_add(avl, box(9), box(228));
-  avl = gpr_avl_add(avl, box(496), box(229));
-  avl = gpr_avl_add(avl, box(750), box(230));
-  avl = gpr_avl_add(avl, box(283), box(231));
-  avl = gpr_avl_add(avl, box(802), box(232));
+  avl = gpr_avl_add(avl, box(9), box(228), NULL);
+  avl = gpr_avl_add(avl, box(496), box(229), NULL);
+  avl = gpr_avl_add(avl, box(750), box(230), NULL);
+  avl = gpr_avl_add(avl, box(283), box(231), NULL);
+  avl = gpr_avl_add(avl, box(802), box(232), NULL);
   avl = remove_int(avl, 352);
-  avl = gpr_avl_add(avl, box(374), box(234));
-  avl = gpr_avl_add(avl, box(6), box(235));
-  avl = gpr_avl_add(avl, box(756), box(236));
-  avl = gpr_avl_add(avl, box(597), box(237));
-  avl = gpr_avl_add(avl, box(661), box(238));
+  avl = gpr_avl_add(avl, box(374), box(234), NULL);
+  avl = gpr_avl_add(avl, box(6), box(235), NULL);
+  avl = gpr_avl_add(avl, box(756), box(236), NULL);
+  avl = gpr_avl_add(avl, box(597), box(237), NULL);
+  avl = gpr_avl_add(avl, box(661), box(238), NULL);
   avl = remove_int(avl, 96);
-  avl = gpr_avl_add(avl, box(894), box(240));
+  avl = gpr_avl_add(avl, box(894), box(240), NULL);
   avl = remove_int(avl, 749);
-  avl = gpr_avl_add(avl, box(71), box(242));
+  avl = gpr_avl_add(avl, box(71), box(242), NULL);
   avl = remove_int(avl, 68);
-  avl = gpr_avl_add(avl, box(388), box(244));
+  avl = gpr_avl_add(avl, box(388), box(244), NULL);
   avl = remove_int(avl, 119);
   avl = remove_int(avl, 856);
-  avl = gpr_avl_add(avl, box(176), box(247));
-  avl = gpr_avl_add(avl, box(993), box(248));
+  avl = gpr_avl_add(avl, box(176), box(247), NULL);
+  avl = gpr_avl_add(avl, box(993), box(248), NULL);
   avl = remove_int(avl, 178);
   avl = remove_int(avl, 781);
   avl = remove_int(avl, 771);
@@ -499,37 +501,37 @@
   avl = remove_int(avl, 157);
   avl = remove_int(avl, 142);
   avl = remove_int(avl, 686);
-  avl = gpr_avl_add(avl, box(779), box(257));
-  avl = gpr_avl_add(avl, box(484), box(258));
+  avl = gpr_avl_add(avl, box(779), box(257), NULL);
+  avl = gpr_avl_add(avl, box(484), box(258), NULL);
   avl = remove_int(avl, 837);
-  avl = gpr_avl_add(avl, box(388), box(260));
+  avl = gpr_avl_add(avl, box(388), box(260), NULL);
   avl = remove_int(avl, 987);
-  avl = gpr_avl_add(avl, box(336), box(262));
+  avl = gpr_avl_add(avl, box(336), box(262), NULL);
   avl = remove_int(avl, 855);
-  avl = gpr_avl_add(avl, box(668), box(264));
+  avl = gpr_avl_add(avl, box(668), box(264), NULL);
   avl = remove_int(avl, 648);
-  avl = gpr_avl_add(avl, box(193), box(266));
+  avl = gpr_avl_add(avl, box(193), box(266), NULL);
   avl = remove_int(avl, 939);
-  avl = gpr_avl_add(avl, box(740), box(268));
-  avl = gpr_avl_add(avl, box(503), box(269));
-  avl = gpr_avl_add(avl, box(765), box(270));
+  avl = gpr_avl_add(avl, box(740), box(268), NULL);
+  avl = gpr_avl_add(avl, box(503), box(269), NULL);
+  avl = gpr_avl_add(avl, box(765), box(270), NULL);
   avl = remove_int(avl, 924);
   avl = remove_int(avl, 513);
-  avl = gpr_avl_add(avl, box(161), box(273));
-  avl = gpr_avl_add(avl, box(502), box(274));
-  avl = gpr_avl_add(avl, box(846), box(275));
+  avl = gpr_avl_add(avl, box(161), box(273), NULL);
+  avl = gpr_avl_add(avl, box(502), box(274), NULL);
+  avl = gpr_avl_add(avl, box(846), box(275), NULL);
   avl = remove_int(avl, 931);
-  avl = gpr_avl_add(avl, box(87), box(277));
-  avl = gpr_avl_add(avl, box(949), box(278));
-  avl = gpr_avl_add(avl, box(548), box(279));
-  avl = gpr_avl_add(avl, box(951), box(280));
+  avl = gpr_avl_add(avl, box(87), box(277), NULL);
+  avl = gpr_avl_add(avl, box(949), box(278), NULL);
+  avl = gpr_avl_add(avl, box(548), box(279), NULL);
+  avl = gpr_avl_add(avl, box(951), box(280), NULL);
   avl = remove_int(avl, 1018);
   avl = remove_int(avl, 568);
-  avl = gpr_avl_add(avl, box(138), box(283));
-  avl = gpr_avl_add(avl, box(202), box(284));
-  avl = gpr_avl_add(avl, box(157), box(285));
-  avl = gpr_avl_add(avl, box(264), box(286));
-  avl = gpr_avl_add(avl, box(370), box(287));
+  avl = gpr_avl_add(avl, box(138), box(283), NULL);
+  avl = gpr_avl_add(avl, box(202), box(284), NULL);
+  avl = gpr_avl_add(avl, box(157), box(285), NULL);
+  avl = gpr_avl_add(avl, box(264), box(286), NULL);
+  avl = gpr_avl_add(avl, box(370), box(287), NULL);
   avl = remove_int(avl, 736);
   avl = remove_int(avl, 751);
   avl = remove_int(avl, 506);
@@ -537,524 +539,524 @@
   avl = remove_int(avl, 358);
   avl = remove_int(avl, 657);
   avl = remove_int(avl, 86);
-  avl = gpr_avl_add(avl, box(876), box(295));
+  avl = gpr_avl_add(avl, box(876), box(295), NULL);
   avl = remove_int(avl, 354);
-  avl = gpr_avl_add(avl, box(134), box(297));
+  avl = gpr_avl_add(avl, box(134), box(297), NULL);
   avl = remove_int(avl, 781);
   avl = remove_int(avl, 183);
-  avl = gpr_avl_add(avl, box(914), box(300));
+  avl = gpr_avl_add(avl, box(914), box(300), NULL);
   avl = remove_int(avl, 926);
   avl = remove_int(avl, 398);
   avl = remove_int(avl, 932);
   avl = remove_int(avl, 804);
   avl = remove_int(avl, 326);
-  avl = gpr_avl_add(avl, box(208), box(306));
-  avl = gpr_avl_add(avl, box(699), box(307));
+  avl = gpr_avl_add(avl, box(208), box(306), NULL);
+  avl = gpr_avl_add(avl, box(699), box(307), NULL);
   avl = remove_int(avl, 576);
   avl = remove_int(avl, 850);
   avl = remove_int(avl, 514);
   avl = remove_int(avl, 676);
   avl = remove_int(avl, 549);
   avl = remove_int(avl, 767);
-  avl = gpr_avl_add(avl, box(58), box(314));
-  avl = gpr_avl_add(avl, box(265), box(315));
-  avl = gpr_avl_add(avl, box(268), box(316));
-  avl = gpr_avl_add(avl, box(103), box(317));
-  avl = gpr_avl_add(avl, box(440), box(318));
+  avl = gpr_avl_add(avl, box(58), box(314), NULL);
+  avl = gpr_avl_add(avl, box(265), box(315), NULL);
+  avl = gpr_avl_add(avl, box(268), box(316), NULL);
+  avl = gpr_avl_add(avl, box(103), box(317), NULL);
+  avl = gpr_avl_add(avl, box(440), box(318), NULL);
   avl = remove_int(avl, 777);
-  avl = gpr_avl_add(avl, box(670), box(320));
+  avl = gpr_avl_add(avl, box(670), box(320), NULL);
   avl = remove_int(avl, 506);
   avl = remove_int(avl, 487);
-  avl = gpr_avl_add(avl, box(421), box(323));
+  avl = gpr_avl_add(avl, box(421), box(323), NULL);
   avl = remove_int(avl, 514);
-  avl = gpr_avl_add(avl, box(701), box(325));
+  avl = gpr_avl_add(avl, box(701), box(325), NULL);
   avl = remove_int(avl, 949);
   avl = remove_int(avl, 872);
   avl = remove_int(avl, 139);
-  avl = gpr_avl_add(avl, box(781), box(329));
-  avl = gpr_avl_add(avl, box(543), box(330));
-  avl = gpr_avl_add(avl, box(147), box(331));
+  avl = gpr_avl_add(avl, box(781), box(329), NULL);
+  avl = gpr_avl_add(avl, box(543), box(330), NULL);
+  avl = gpr_avl_add(avl, box(147), box(331), NULL);
   avl = remove_int(avl, 190);
-  avl = gpr_avl_add(avl, box(453), box(333));
+  avl = gpr_avl_add(avl, box(453), box(333), NULL);
   avl = remove_int(avl, 262);
   avl = remove_int(avl, 850);
   avl = remove_int(avl, 286);
   avl = remove_int(avl, 787);
-  avl = gpr_avl_add(avl, box(514), box(338));
+  avl = gpr_avl_add(avl, box(514), box(338), NULL);
   avl = remove_int(avl, 812);
-  avl = gpr_avl_add(avl, box(431), box(340));
-  avl = gpr_avl_add(avl, box(8), box(341));
+  avl = gpr_avl_add(avl, box(431), box(340), NULL);
+  avl = gpr_avl_add(avl, box(8), box(341), NULL);
   avl = remove_int(avl, 843);
-  avl = gpr_avl_add(avl, box(831), box(343));
+  avl = gpr_avl_add(avl, box(831), box(343), NULL);
   avl = remove_int(avl, 472);
   avl = remove_int(avl, 157);
-  avl = gpr_avl_add(avl, box(612), box(346));
-  avl = gpr_avl_add(avl, box(802), box(347));
+  avl = gpr_avl_add(avl, box(612), box(346), NULL);
+  avl = gpr_avl_add(avl, box(802), box(347), NULL);
   avl = remove_int(avl, 554);
-  avl = gpr_avl_add(avl, box(409), box(349));
-  avl = gpr_avl_add(avl, box(439), box(350));
-  avl = gpr_avl_add(avl, box(725), box(351));
-  avl = gpr_avl_add(avl, box(568), box(352));
+  avl = gpr_avl_add(avl, box(409), box(349), NULL);
+  avl = gpr_avl_add(avl, box(439), box(350), NULL);
+  avl = gpr_avl_add(avl, box(725), box(351), NULL);
+  avl = gpr_avl_add(avl, box(568), box(352), NULL);
   avl = remove_int(avl, 475);
   avl = remove_int(avl, 672);
   avl = remove_int(avl, 62);
   avl = remove_int(avl, 753);
-  avl = gpr_avl_add(avl, box(435), box(357));
-  avl = gpr_avl_add(avl, box(950), box(358));
-  avl = gpr_avl_add(avl, box(532), box(359));
-  avl = gpr_avl_add(avl, box(832), box(360));
+  avl = gpr_avl_add(avl, box(435), box(357), NULL);
+  avl = gpr_avl_add(avl, box(950), box(358), NULL);
+  avl = gpr_avl_add(avl, box(532), box(359), NULL);
+  avl = gpr_avl_add(avl, box(832), box(360), NULL);
   avl = remove_int(avl, 390);
-  avl = gpr_avl_add(avl, box(993), box(362));
+  avl = gpr_avl_add(avl, box(993), box(362), NULL);
   avl = remove_int(avl, 198);
   avl = remove_int(avl, 401);
-  avl = gpr_avl_add(avl, box(316), box(365));
+  avl = gpr_avl_add(avl, box(316), box(365), NULL);
   avl = remove_int(avl, 843);
-  avl = gpr_avl_add(avl, box(541), box(367));
-  avl = gpr_avl_add(avl, box(505), box(368));
+  avl = gpr_avl_add(avl, box(541), box(367), NULL);
+  avl = gpr_avl_add(avl, box(505), box(368), NULL);
   avl = remove_int(avl, 445);
   avl = remove_int(avl, 256);
-  avl = gpr_avl_add(avl, box(232), box(371));
+  avl = gpr_avl_add(avl, box(232), box(371), NULL);
   avl = remove_int(avl, 577);
   avl = remove_int(avl, 558);
-  avl = gpr_avl_add(avl, box(910), box(374));
+  avl = gpr_avl_add(avl, box(910), box(374), NULL);
   avl = remove_int(avl, 902);
   avl = remove_int(avl, 755);
   avl = remove_int(avl, 114);
   avl = remove_int(avl, 438);
   avl = remove_int(avl, 224);
-  avl = gpr_avl_add(avl, box(920), box(380));
-  avl = gpr_avl_add(avl, box(655), box(381));
+  avl = gpr_avl_add(avl, box(920), box(380), NULL);
+  avl = gpr_avl_add(avl, box(655), box(381), NULL);
   avl = remove_int(avl, 557);
   avl = remove_int(avl, 102);
   avl = remove_int(avl, 165);
-  avl = gpr_avl_add(avl, box(191), box(385));
+  avl = gpr_avl_add(avl, box(191), box(385), NULL);
   avl = remove_int(avl, 30);
-  avl = gpr_avl_add(avl, box(406), box(387));
-  avl = gpr_avl_add(avl, box(66), box(388));
-  avl = gpr_avl_add(avl, box(87), box(389));
+  avl = gpr_avl_add(avl, box(406), box(387), NULL);
+  avl = gpr_avl_add(avl, box(66), box(388), NULL);
+  avl = gpr_avl_add(avl, box(87), box(389), NULL);
   avl = remove_int(avl, 7);
   avl = remove_int(avl, 671);
-  avl = gpr_avl_add(avl, box(234), box(392));
+  avl = gpr_avl_add(avl, box(234), box(392), NULL);
   avl = remove_int(avl, 463);
-  avl = gpr_avl_add(avl, box(75), box(394));
-  avl = gpr_avl_add(avl, box(487), box(395));
+  avl = gpr_avl_add(avl, box(75), box(394), NULL);
+  avl = gpr_avl_add(avl, box(487), box(395), NULL);
   avl = remove_int(avl, 203);
-  avl = gpr_avl_add(avl, box(711), box(397));
+  avl = gpr_avl_add(avl, box(711), box(397), NULL);
   avl = remove_int(avl, 291);
   avl = remove_int(avl, 798);
   avl = remove_int(avl, 337);
-  avl = gpr_avl_add(avl, box(877), box(401));
-  avl = gpr_avl_add(avl, box(388), box(402));
+  avl = gpr_avl_add(avl, box(877), box(401), NULL);
+  avl = gpr_avl_add(avl, box(388), box(402), NULL);
   avl = remove_int(avl, 975);
-  avl = gpr_avl_add(avl, box(200), box(404));
-  avl = gpr_avl_add(avl, box(408), box(405));
-  avl = gpr_avl_add(avl, box(3), box(406));
-  avl = gpr_avl_add(avl, box(971), box(407));
+  avl = gpr_avl_add(avl, box(200), box(404), NULL);
+  avl = gpr_avl_add(avl, box(408), box(405), NULL);
+  avl = gpr_avl_add(avl, box(3), box(406), NULL);
+  avl = gpr_avl_add(avl, box(971), box(407), NULL);
   avl = remove_int(avl, 841);
   avl = remove_int(avl, 910);
   avl = remove_int(avl, 74);
   avl = remove_int(avl, 888);
-  avl = gpr_avl_add(avl, box(492), box(412));
+  avl = gpr_avl_add(avl, box(492), box(412), NULL);
   avl = remove_int(avl, 14);
   avl = remove_int(avl, 364);
-  avl = gpr_avl_add(avl, box(215), box(415));
+  avl = gpr_avl_add(avl, box(215), box(415), NULL);
   avl = remove_int(avl, 778);
   avl = remove_int(avl, 45);
-  avl = gpr_avl_add(avl, box(328), box(418));
-  avl = gpr_avl_add(avl, box(597), box(419));
+  avl = gpr_avl_add(avl, box(328), box(418), NULL);
+  avl = gpr_avl_add(avl, box(597), box(419), NULL);
   avl = remove_int(avl, 34);
-  avl = gpr_avl_add(avl, box(736), box(421));
+  avl = gpr_avl_add(avl, box(736), box(421), NULL);
   avl = remove_int(avl, 37);
-  avl = gpr_avl_add(avl, box(275), box(423));
-  avl = gpr_avl_add(avl, box(70), box(424));
-  avl = gpr_avl_add(avl, box(771), box(425));
+  avl = gpr_avl_add(avl, box(275), box(423), NULL);
+  avl = gpr_avl_add(avl, box(70), box(424), NULL);
+  avl = gpr_avl_add(avl, box(771), box(425), NULL);
   avl = remove_int(avl, 536);
   avl = remove_int(avl, 421);
-  avl = gpr_avl_add(avl, box(186), box(428));
-  avl = gpr_avl_add(avl, box(788), box(429));
-  avl = gpr_avl_add(avl, box(224), box(430));
+  avl = gpr_avl_add(avl, box(186), box(428), NULL);
+  avl = gpr_avl_add(avl, box(788), box(429), NULL);
+  avl = gpr_avl_add(avl, box(224), box(430), NULL);
   avl = remove_int(avl, 228);
-  avl = gpr_avl_add(avl, box(48), box(432));
-  avl = gpr_avl_add(avl, box(120), box(433));
-  avl = gpr_avl_add(avl, box(269), box(434));
-  avl = gpr_avl_add(avl, box(904), box(435));
+  avl = gpr_avl_add(avl, box(48), box(432), NULL);
+  avl = gpr_avl_add(avl, box(120), box(433), NULL);
+  avl = gpr_avl_add(avl, box(269), box(434), NULL);
+  avl = gpr_avl_add(avl, box(904), box(435), NULL);
   avl = remove_int(avl, 699);
-  avl = gpr_avl_add(avl, box(340), box(437));
+  avl = gpr_avl_add(avl, box(340), box(437), NULL);
   avl = remove_int(avl, 276);
-  avl = gpr_avl_add(avl, box(591), box(439));
-  avl = gpr_avl_add(avl, box(778), box(440));
+  avl = gpr_avl_add(avl, box(591), box(439), NULL);
+  avl = gpr_avl_add(avl, box(778), box(440), NULL);
   avl = remove_int(avl, 490);
   avl = remove_int(avl, 973);
-  avl = gpr_avl_add(avl, box(294), box(443));
-  avl = gpr_avl_add(avl, box(323), box(444));
+  avl = gpr_avl_add(avl, box(294), box(443), NULL);
+  avl = gpr_avl_add(avl, box(323), box(444), NULL);
   avl = remove_int(avl, 685);
-  avl = gpr_avl_add(avl, box(38), box(446));
-  avl = gpr_avl_add(avl, box(525), box(447));
+  avl = gpr_avl_add(avl, box(38), box(446), NULL);
+  avl = gpr_avl_add(avl, box(525), box(447), NULL);
   avl = remove_int(avl, 162);
-  avl = gpr_avl_add(avl, box(462), box(449));
-  avl = gpr_avl_add(avl, box(340), box(450));
+  avl = gpr_avl_add(avl, box(462), box(449), NULL);
+  avl = gpr_avl_add(avl, box(340), box(450), NULL);
   avl = remove_int(avl, 734);
   avl = remove_int(avl, 959);
-  avl = gpr_avl_add(avl, box(752), box(453));
-  avl = gpr_avl_add(avl, box(667), box(454));
+  avl = gpr_avl_add(avl, box(752), box(453), NULL);
+  avl = gpr_avl_add(avl, box(667), box(454), NULL);
   avl = remove_int(avl, 558);
   avl = remove_int(avl, 657);
-  avl = gpr_avl_add(avl, box(711), box(457));
+  avl = gpr_avl_add(avl, box(711), box(457), NULL);
   avl = remove_int(avl, 937);
-  avl = gpr_avl_add(avl, box(741), box(459));
-  avl = gpr_avl_add(avl, box(40), box(460));
+  avl = gpr_avl_add(avl, box(741), box(459), NULL);
+  avl = gpr_avl_add(avl, box(40), box(460), NULL);
   avl = remove_int(avl, 784);
-  avl = gpr_avl_add(avl, box(292), box(462));
+  avl = gpr_avl_add(avl, box(292), box(462), NULL);
   avl = remove_int(avl, 164);
   avl = remove_int(avl, 931);
   avl = remove_int(avl, 886);
-  avl = gpr_avl_add(avl, box(968), box(466));
+  avl = gpr_avl_add(avl, box(968), box(466), NULL);
   avl = remove_int(avl, 263);
-  avl = gpr_avl_add(avl, box(647), box(468));
-  avl = gpr_avl_add(avl, box(92), box(469));
+  avl = gpr_avl_add(avl, box(647), box(468), NULL);
+  avl = gpr_avl_add(avl, box(92), box(469), NULL);
   avl = remove_int(avl, 310);
-  avl = gpr_avl_add(avl, box(711), box(471));
-  avl = gpr_avl_add(avl, box(675), box(472));
+  avl = gpr_avl_add(avl, box(711), box(471), NULL);
+  avl = gpr_avl_add(avl, box(675), box(472), NULL);
   avl = remove_int(avl, 549);
-  avl = gpr_avl_add(avl, box(380), box(474));
+  avl = gpr_avl_add(avl, box(380), box(474), NULL);
   avl = remove_int(avl, 825);
-  avl = gpr_avl_add(avl, box(668), box(476));
+  avl = gpr_avl_add(avl, box(668), box(476), NULL);
   avl = remove_int(avl, 498);
-  avl = gpr_avl_add(avl, box(870), box(478));
-  avl = gpr_avl_add(avl, box(391), box(479));
-  avl = gpr_avl_add(avl, box(264), box(480));
+  avl = gpr_avl_add(avl, box(870), box(478), NULL);
+  avl = gpr_avl_add(avl, box(391), box(479), NULL);
+  avl = gpr_avl_add(avl, box(264), box(480), NULL);
   avl = remove_int(avl, 1);
   avl = remove_int(avl, 849);
   avl = remove_int(avl, 88);
   avl = remove_int(avl, 255);
   avl = remove_int(avl, 763);
   avl = remove_int(avl, 831);
-  avl = gpr_avl_add(avl, box(508), box(487));
+  avl = gpr_avl_add(avl, box(508), box(487), NULL);
   avl = remove_int(avl, 849);
   avl = remove_int(avl, 47);
-  avl = gpr_avl_add(avl, box(299), box(490));
+  avl = gpr_avl_add(avl, box(299), box(490), NULL);
   avl = remove_int(avl, 625);
   avl = remove_int(avl, 433);
   avl = remove_int(avl, 904);
   avl = remove_int(avl, 761);
-  avl = gpr_avl_add(avl, box(33), box(495));
-  avl = gpr_avl_add(avl, box(524), box(496));
+  avl = gpr_avl_add(avl, box(33), box(495), NULL);
+  avl = gpr_avl_add(avl, box(524), box(496), NULL);
   avl = remove_int(avl, 210);
   avl = remove_int(avl, 299);
-  avl = gpr_avl_add(avl, box(823), box(499));
+  avl = gpr_avl_add(avl, box(823), box(499), NULL);
   avl = remove_int(avl, 479);
   avl = remove_int(avl, 96);
   avl = remove_int(avl, 1013);
-  avl = gpr_avl_add(avl, box(768), box(503));
+  avl = gpr_avl_add(avl, box(768), box(503), NULL);
   avl = remove_int(avl, 638);
   avl = remove_int(avl, 20);
-  avl = gpr_avl_add(avl, box(663), box(506));
+  avl = gpr_avl_add(avl, box(663), box(506), NULL);
   avl = remove_int(avl, 882);
-  avl = gpr_avl_add(avl, box(745), box(508));
+  avl = gpr_avl_add(avl, box(745), box(508), NULL);
   avl = remove_int(avl, 352);
-  avl = gpr_avl_add(avl, box(10), box(510));
+  avl = gpr_avl_add(avl, box(10), box(510), NULL);
   avl = remove_int(avl, 484);
-  avl = gpr_avl_add(avl, box(420), box(512));
-  avl = gpr_avl_add(avl, box(884), box(513));
-  avl = gpr_avl_add(avl, box(993), box(514));
-  avl = gpr_avl_add(avl, box(251), box(515));
+  avl = gpr_avl_add(avl, box(420), box(512), NULL);
+  avl = gpr_avl_add(avl, box(884), box(513), NULL);
+  avl = gpr_avl_add(avl, box(993), box(514), NULL);
+  avl = gpr_avl_add(avl, box(251), box(515), NULL);
   avl = remove_int(avl, 222);
-  avl = gpr_avl_add(avl, box(734), box(517));
-  avl = gpr_avl_add(avl, box(952), box(518));
+  avl = gpr_avl_add(avl, box(734), box(517), NULL);
+  avl = gpr_avl_add(avl, box(952), box(518), NULL);
   avl = remove_int(avl, 26);
   avl = remove_int(avl, 270);
   avl = remove_int(avl, 481);
   avl = remove_int(avl, 693);
   avl = remove_int(avl, 1006);
-  avl = gpr_avl_add(avl, box(77), box(524));
+  avl = gpr_avl_add(avl, box(77), box(524), NULL);
   avl = remove_int(avl, 897);
-  avl = gpr_avl_add(avl, box(719), box(526));
-  avl = gpr_avl_add(avl, box(622), box(527));
+  avl = gpr_avl_add(avl, box(719), box(526), NULL);
+  avl = gpr_avl_add(avl, box(622), box(527), NULL);
   avl = remove_int(avl, 28);
   avl = remove_int(avl, 836);
   avl = remove_int(avl, 142);
-  avl = gpr_avl_add(avl, box(445), box(531));
-  avl = gpr_avl_add(avl, box(410), box(532));
+  avl = gpr_avl_add(avl, box(445), box(531), NULL);
+  avl = gpr_avl_add(avl, box(410), box(532), NULL);
   avl = remove_int(avl, 575);
-  avl = gpr_avl_add(avl, box(634), box(534));
-  avl = gpr_avl_add(avl, box(906), box(535));
+  avl = gpr_avl_add(avl, box(634), box(534), NULL);
+  avl = gpr_avl_add(avl, box(906), box(535), NULL);
   avl = remove_int(avl, 649);
-  avl = gpr_avl_add(avl, box(813), box(537));
+  avl = gpr_avl_add(avl, box(813), box(537), NULL);
   avl = remove_int(avl, 702);
   avl = remove_int(avl, 732);
-  avl = gpr_avl_add(avl, box(105), box(540));
-  avl = gpr_avl_add(avl, box(867), box(541));
+  avl = gpr_avl_add(avl, box(105), box(540), NULL);
+  avl = gpr_avl_add(avl, box(867), box(541), NULL);
   avl = remove_int(avl, 964);
   avl = remove_int(avl, 941);
-  avl = gpr_avl_add(avl, box(947), box(544));
+  avl = gpr_avl_add(avl, box(947), box(544), NULL);
   avl = remove_int(avl, 990);
-  avl = gpr_avl_add(avl, box(816), box(546));
+  avl = gpr_avl_add(avl, box(816), box(546), NULL);
   avl = remove_int(avl, 429);
   avl = remove_int(avl, 567);
   avl = remove_int(avl, 541);
   avl = remove_int(avl, 583);
-  avl = gpr_avl_add(avl, box(57), box(551));
-  avl = gpr_avl_add(avl, box(786), box(552));
-  avl = gpr_avl_add(avl, box(526), box(553));
+  avl = gpr_avl_add(avl, box(57), box(551), NULL);
+  avl = gpr_avl_add(avl, box(786), box(552), NULL);
+  avl = gpr_avl_add(avl, box(526), box(553), NULL);
   avl = remove_int(avl, 642);
   avl = remove_int(avl, 220);
   avl = remove_int(avl, 840);
   avl = remove_int(avl, 548);
-  avl = gpr_avl_add(avl, box(528), box(558));
-  avl = gpr_avl_add(avl, box(749), box(559));
-  avl = gpr_avl_add(avl, box(194), box(560));
+  avl = gpr_avl_add(avl, box(528), box(558), NULL);
+  avl = gpr_avl_add(avl, box(749), box(559), NULL);
+  avl = gpr_avl_add(avl, box(194), box(560), NULL);
   avl = remove_int(avl, 517);
-  avl = gpr_avl_add(avl, box(102), box(562));
+  avl = gpr_avl_add(avl, box(102), box(562), NULL);
   avl = remove_int(avl, 189);
-  avl = gpr_avl_add(avl, box(927), box(564));
+  avl = gpr_avl_add(avl, box(927), box(564), NULL);
   avl = remove_int(avl, 846);
   avl = remove_int(avl, 130);
-  avl = gpr_avl_add(avl, box(694), box(567));
+  avl = gpr_avl_add(avl, box(694), box(567), NULL);
   avl = remove_int(avl, 750);
-  avl = gpr_avl_add(avl, box(357), box(569));
+  avl = gpr_avl_add(avl, box(357), box(569), NULL);
   avl = remove_int(avl, 431);
   avl = remove_int(avl, 91);
-  avl = gpr_avl_add(avl, box(640), box(572));
+  avl = gpr_avl_add(avl, box(640), box(572), NULL);
   avl = remove_int(avl, 4);
-  avl = gpr_avl_add(avl, box(81), box(574));
-  avl = gpr_avl_add(avl, box(595), box(575));
+  avl = gpr_avl_add(avl, box(81), box(574), NULL);
+  avl = gpr_avl_add(avl, box(595), box(575), NULL);
   avl = remove_int(avl, 444);
   avl = remove_int(avl, 262);
   avl = remove_int(avl, 11);
-  avl = gpr_avl_add(avl, box(192), box(579));
-  avl = gpr_avl_add(avl, box(158), box(580));
+  avl = gpr_avl_add(avl, box(192), box(579), NULL);
+  avl = gpr_avl_add(avl, box(158), box(580), NULL);
   avl = remove_int(avl, 401);
   avl = remove_int(avl, 918);
-  avl = gpr_avl_add(avl, box(180), box(583));
+  avl = gpr_avl_add(avl, box(180), box(583), NULL);
   avl = remove_int(avl, 268);
-  avl = gpr_avl_add(avl, box(1012), box(585));
-  avl = gpr_avl_add(avl, box(90), box(586));
-  avl = gpr_avl_add(avl, box(946), box(587));
+  avl = gpr_avl_add(avl, box(1012), box(585), NULL);
+  avl = gpr_avl_add(avl, box(90), box(586), NULL);
+  avl = gpr_avl_add(avl, box(946), box(587), NULL);
   avl = remove_int(avl, 719);
-  avl = gpr_avl_add(avl, box(874), box(589));
-  avl = gpr_avl_add(avl, box(679), box(590));
+  avl = gpr_avl_add(avl, box(874), box(589), NULL);
+  avl = gpr_avl_add(avl, box(679), box(590), NULL);
   avl = remove_int(avl, 53);
   avl = remove_int(avl, 534);
-  avl = gpr_avl_add(avl, box(646), box(593));
-  avl = gpr_avl_add(avl, box(767), box(594));
-  avl = gpr_avl_add(avl, box(460), box(595));
-  avl = gpr_avl_add(avl, box(852), box(596));
-  avl = gpr_avl_add(avl, box(189), box(597));
+  avl = gpr_avl_add(avl, box(646), box(593), NULL);
+  avl = gpr_avl_add(avl, box(767), box(594), NULL);
+  avl = gpr_avl_add(avl, box(460), box(595), NULL);
+  avl = gpr_avl_add(avl, box(852), box(596), NULL);
+  avl = gpr_avl_add(avl, box(189), box(597), NULL);
   avl = remove_int(avl, 932);
   avl = remove_int(avl, 366);
   avl = remove_int(avl, 907);
-  avl = gpr_avl_add(avl, box(875), box(601));
-  avl = gpr_avl_add(avl, box(434), box(602));
-  avl = gpr_avl_add(avl, box(704), box(603));
-  avl = gpr_avl_add(avl, box(724), box(604));
-  avl = gpr_avl_add(avl, box(930), box(605));
-  avl = gpr_avl_add(avl, box(1000), box(606));
+  avl = gpr_avl_add(avl, box(875), box(601), NULL);
+  avl = gpr_avl_add(avl, box(434), box(602), NULL);
+  avl = gpr_avl_add(avl, box(704), box(603), NULL);
+  avl = gpr_avl_add(avl, box(724), box(604), NULL);
+  avl = gpr_avl_add(avl, box(930), box(605), NULL);
+  avl = gpr_avl_add(avl, box(1000), box(606), NULL);
   avl = remove_int(avl, 479);
-  avl = gpr_avl_add(avl, box(275), box(608));
+  avl = gpr_avl_add(avl, box(275), box(608), NULL);
   avl = remove_int(avl, 32);
-  avl = gpr_avl_add(avl, box(939), box(610));
+  avl = gpr_avl_add(avl, box(939), box(610), NULL);
   avl = remove_int(avl, 943);
   avl = remove_int(avl, 329);
-  avl = gpr_avl_add(avl, box(490), box(613));
+  avl = gpr_avl_add(avl, box(490), box(613), NULL);
   avl = remove_int(avl, 477);
   avl = remove_int(avl, 414);
   avl = remove_int(avl, 187);
   avl = remove_int(avl, 334);
-  avl = gpr_avl_add(avl, box(40), box(618));
+  avl = gpr_avl_add(avl, box(40), box(618), NULL);
   avl = remove_int(avl, 751);
-  avl = gpr_avl_add(avl, box(568), box(620));
-  avl = gpr_avl_add(avl, box(120), box(621));
-  avl = gpr_avl_add(avl, box(617), box(622));
-  avl = gpr_avl_add(avl, box(32), box(623));
+  avl = gpr_avl_add(avl, box(568), box(620), NULL);
+  avl = gpr_avl_add(avl, box(120), box(621), NULL);
+  avl = gpr_avl_add(avl, box(617), box(622), NULL);
+  avl = gpr_avl_add(avl, box(32), box(623), NULL);
   avl = remove_int(avl, 701);
-  avl = gpr_avl_add(avl, box(910), box(625));
+  avl = gpr_avl_add(avl, box(910), box(625), NULL);
   avl = remove_int(avl, 557);
   avl = remove_int(avl, 361);
   avl = remove_int(avl, 937);
   avl = remove_int(avl, 100);
   avl = remove_int(avl, 684);
-  avl = gpr_avl_add(avl, box(751), box(631));
+  avl = gpr_avl_add(avl, box(751), box(631), NULL);
   avl = remove_int(avl, 781);
   avl = remove_int(avl, 469);
   avl = remove_int(avl, 75);
   avl = remove_int(avl, 561);
-  avl = gpr_avl_add(avl, box(854), box(636));
+  avl = gpr_avl_add(avl, box(854), box(636), NULL);
   avl = remove_int(avl, 164);
   avl = remove_int(avl, 258);
   avl = remove_int(avl, 315);
   avl = remove_int(avl, 261);
-  avl = gpr_avl_add(avl, box(552), box(641));
-  avl = gpr_avl_add(avl, box(6), box(642));
-  avl = gpr_avl_add(avl, box(680), box(643));
+  avl = gpr_avl_add(avl, box(552), box(641), NULL);
+  avl = gpr_avl_add(avl, box(6), box(642), NULL);
+  avl = gpr_avl_add(avl, box(680), box(643), NULL);
   avl = remove_int(avl, 741);
   avl = remove_int(avl, 309);
   avl = remove_int(avl, 272);
-  avl = gpr_avl_add(avl, box(249), box(647));
+  avl = gpr_avl_add(avl, box(249), box(647), NULL);
   avl = remove_int(avl, 97);
   avl = remove_int(avl, 850);
-  avl = gpr_avl_add(avl, box(915), box(650));
-  avl = gpr_avl_add(avl, box(816), box(651));
-  avl = gpr_avl_add(avl, box(45), box(652));
-  avl = gpr_avl_add(avl, box(168), box(653));
+  avl = gpr_avl_add(avl, box(915), box(650), NULL);
+  avl = gpr_avl_add(avl, box(816), box(651), NULL);
+  avl = gpr_avl_add(avl, box(45), box(652), NULL);
+  avl = gpr_avl_add(avl, box(168), box(653), NULL);
   avl = remove_int(avl, 153);
   avl = remove_int(avl, 239);
-  avl = gpr_avl_add(avl, box(684), box(656));
-  avl = gpr_avl_add(avl, box(208), box(657));
-  avl = gpr_avl_add(avl, box(681), box(658));
-  avl = gpr_avl_add(avl, box(609), box(659));
-  avl = gpr_avl_add(avl, box(645), box(660));
+  avl = gpr_avl_add(avl, box(684), box(656), NULL);
+  avl = gpr_avl_add(avl, box(208), box(657), NULL);
+  avl = gpr_avl_add(avl, box(681), box(658), NULL);
+  avl = gpr_avl_add(avl, box(609), box(659), NULL);
+  avl = gpr_avl_add(avl, box(645), box(660), NULL);
   avl = remove_int(avl, 799);
-  avl = gpr_avl_add(avl, box(955), box(662));
-  avl = gpr_avl_add(avl, box(946), box(663));
-  avl = gpr_avl_add(avl, box(744), box(664));
-  avl = gpr_avl_add(avl, box(201), box(665));
-  avl = gpr_avl_add(avl, box(136), box(666));
+  avl = gpr_avl_add(avl, box(955), box(662), NULL);
+  avl = gpr_avl_add(avl, box(946), box(663), NULL);
+  avl = gpr_avl_add(avl, box(744), box(664), NULL);
+  avl = gpr_avl_add(avl, box(201), box(665), NULL);
+  avl = gpr_avl_add(avl, box(136), box(666), NULL);
   avl = remove_int(avl, 357);
-  avl = gpr_avl_add(avl, box(974), box(668));
+  avl = gpr_avl_add(avl, box(974), box(668), NULL);
   avl = remove_int(avl, 485);
-  avl = gpr_avl_add(avl, box(1009), box(670));
-  avl = gpr_avl_add(avl, box(517), box(671));
+  avl = gpr_avl_add(avl, box(1009), box(670), NULL);
+  avl = gpr_avl_add(avl, box(517), box(671), NULL);
   avl = remove_int(avl, 491);
-  avl = gpr_avl_add(avl, box(336), box(673));
-  avl = gpr_avl_add(avl, box(589), box(674));
+  avl = gpr_avl_add(avl, box(336), box(673), NULL);
+  avl = gpr_avl_add(avl, box(589), box(674), NULL);
   avl = remove_int(avl, 546);
   avl = remove_int(avl, 840);
   avl = remove_int(avl, 104);
   avl = remove_int(avl, 347);
-  avl = gpr_avl_add(avl, box(801), box(679));
+  avl = gpr_avl_add(avl, box(801), box(679), NULL);
   avl = remove_int(avl, 799);
   avl = remove_int(avl, 702);
   avl = remove_int(avl, 996);
   avl = remove_int(avl, 93);
-  avl = gpr_avl_add(avl, box(561), box(684));
-  avl = gpr_avl_add(avl, box(25), box(685));
+  avl = gpr_avl_add(avl, box(561), box(684), NULL);
+  avl = gpr_avl_add(avl, box(25), box(685), NULL);
   avl = remove_int(avl, 278);
-  avl = gpr_avl_add(avl, box(191), box(687));
+  avl = gpr_avl_add(avl, box(191), box(687), NULL);
   avl = remove_int(avl, 243);
   avl = remove_int(avl, 918);
   avl = remove_int(avl, 449);
-  avl = gpr_avl_add(avl, box(19), box(691));
-  avl = gpr_avl_add(avl, box(762), box(692));
-  avl = gpr_avl_add(avl, box(13), box(693));
-  avl = gpr_avl_add(avl, box(151), box(694));
-  avl = gpr_avl_add(avl, box(152), box(695));
-  avl = gpr_avl_add(avl, box(793), box(696));
+  avl = gpr_avl_add(avl, box(19), box(691), NULL);
+  avl = gpr_avl_add(avl, box(762), box(692), NULL);
+  avl = gpr_avl_add(avl, box(13), box(693), NULL);
+  avl = gpr_avl_add(avl, box(151), box(694), NULL);
+  avl = gpr_avl_add(avl, box(152), box(695), NULL);
+  avl = gpr_avl_add(avl, box(793), box(696), NULL);
   avl = remove_int(avl, 862);
   avl = remove_int(avl, 890);
-  avl = gpr_avl_add(avl, box(687), box(699));
-  avl = gpr_avl_add(avl, box(509), box(700));
-  avl = gpr_avl_add(avl, box(973), box(701));
+  avl = gpr_avl_add(avl, box(687), box(699), NULL);
+  avl = gpr_avl_add(avl, box(509), box(700), NULL);
+  avl = gpr_avl_add(avl, box(973), box(701), NULL);
   avl = remove_int(avl, 230);
-  avl = gpr_avl_add(avl, box(532), box(703));
+  avl = gpr_avl_add(avl, box(532), box(703), NULL);
   avl = remove_int(avl, 668);
-  avl = gpr_avl_add(avl, box(281), box(705));
-  avl = gpr_avl_add(avl, box(867), box(706));
-  avl = gpr_avl_add(avl, box(359), box(707));
+  avl = gpr_avl_add(avl, box(281), box(705), NULL);
+  avl = gpr_avl_add(avl, box(867), box(706), NULL);
+  avl = gpr_avl_add(avl, box(359), box(707), NULL);
   avl = remove_int(avl, 425);
-  avl = gpr_avl_add(avl, box(691), box(709));
-  avl = gpr_avl_add(avl, box(163), box(710));
-  avl = gpr_avl_add(avl, box(502), box(711));
+  avl = gpr_avl_add(avl, box(691), box(709), NULL);
+  avl = gpr_avl_add(avl, box(163), box(710), NULL);
+  avl = gpr_avl_add(avl, box(502), box(711), NULL);
   avl = remove_int(avl, 674);
-  avl = gpr_avl_add(avl, box(697), box(713));
+  avl = gpr_avl_add(avl, box(697), box(713), NULL);
   avl = remove_int(avl, 271);
-  avl = gpr_avl_add(avl, box(968), box(715));
-  avl = gpr_avl_add(avl, box(48), box(716));
+  avl = gpr_avl_add(avl, box(968), box(715), NULL);
+  avl = gpr_avl_add(avl, box(48), box(716), NULL);
   avl = remove_int(avl, 543);
-  avl = gpr_avl_add(avl, box(35), box(718));
-  avl = gpr_avl_add(avl, box(751), box(719));
-  avl = gpr_avl_add(avl, box(478), box(720));
+  avl = gpr_avl_add(avl, box(35), box(718), NULL);
+  avl = gpr_avl_add(avl, box(751), box(719), NULL);
+  avl = gpr_avl_add(avl, box(478), box(720), NULL);
   avl = remove_int(avl, 797);
   avl = remove_int(avl, 309);
-  avl = gpr_avl_add(avl, box(927), box(723));
+  avl = gpr_avl_add(avl, box(927), box(723), NULL);
   avl = remove_int(avl, 504);
-  avl = gpr_avl_add(avl, box(286), box(725));
-  avl = gpr_avl_add(avl, box(413), box(726));
-  avl = gpr_avl_add(avl, box(599), box(727));
+  avl = gpr_avl_add(avl, box(286), box(725), NULL);
+  avl = gpr_avl_add(avl, box(413), box(726), NULL);
+  avl = gpr_avl_add(avl, box(599), box(727), NULL);
   avl = remove_int(avl, 105);
   avl = remove_int(avl, 605);
-  avl = gpr_avl_add(avl, box(632), box(730));
-  avl = gpr_avl_add(avl, box(133), box(731));
+  avl = gpr_avl_add(avl, box(632), box(730), NULL);
+  avl = gpr_avl_add(avl, box(133), box(731), NULL);
   avl = remove_int(avl, 443);
-  avl = gpr_avl_add(avl, box(958), box(733));
-  avl = gpr_avl_add(avl, box(729), box(734));
+  avl = gpr_avl_add(avl, box(958), box(733), NULL);
+  avl = gpr_avl_add(avl, box(729), box(734), NULL);
   avl = remove_int(avl, 158);
-  avl = gpr_avl_add(avl, box(694), box(736));
-  avl = gpr_avl_add(avl, box(505), box(737));
+  avl = gpr_avl_add(avl, box(694), box(736), NULL);
+  avl = gpr_avl_add(avl, box(505), box(737), NULL);
   avl = remove_int(avl, 63);
   avl = remove_int(avl, 714);
-  avl = gpr_avl_add(avl, box(1002), box(740));
+  avl = gpr_avl_add(avl, box(1002), box(740), NULL);
   avl = remove_int(avl, 211);
-  avl = gpr_avl_add(avl, box(765), box(742));
-  avl = gpr_avl_add(avl, box(455), box(743));
+  avl = gpr_avl_add(avl, box(765), box(742), NULL);
+  avl = gpr_avl_add(avl, box(455), box(743), NULL);
   avl = remove_int(avl, 59);
   avl = remove_int(avl, 224);
-  avl = gpr_avl_add(avl, box(586), box(746));
-  avl = gpr_avl_add(avl, box(348), box(747));
+  avl = gpr_avl_add(avl, box(586), box(746), NULL);
+  avl = gpr_avl_add(avl, box(348), box(747), NULL);
   avl = remove_int(avl, 10);
   avl = remove_int(avl, 484);
-  avl = gpr_avl_add(avl, box(968), box(750));
-  avl = gpr_avl_add(avl, box(923), box(751));
+  avl = gpr_avl_add(avl, box(968), box(750), NULL);
+  avl = gpr_avl_add(avl, box(923), box(751), NULL);
   avl = remove_int(avl, 573);
   avl = remove_int(avl, 617);
-  avl = gpr_avl_add(avl, box(812), box(754));
-  avl = gpr_avl_add(avl, box(179), box(755));
+  avl = gpr_avl_add(avl, box(812), box(754), NULL);
+  avl = gpr_avl_add(avl, box(179), box(755), NULL);
   avl = remove_int(avl, 284);
   avl = remove_int(avl, 157);
   avl = remove_int(avl, 177);
   avl = remove_int(avl, 896);
-  avl = gpr_avl_add(avl, box(649), box(760));
-  avl = gpr_avl_add(avl, box(927), box(761));
-  avl = gpr_avl_add(avl, box(454), box(762));
-  avl = gpr_avl_add(avl, box(217), box(763));
+  avl = gpr_avl_add(avl, box(649), box(760), NULL);
+  avl = gpr_avl_add(avl, box(927), box(761), NULL);
+  avl = gpr_avl_add(avl, box(454), box(762), NULL);
+  avl = gpr_avl_add(avl, box(217), box(763), NULL);
   avl = remove_int(avl, 534);
-  avl = gpr_avl_add(avl, box(180), box(765));
-  avl = gpr_avl_add(avl, box(319), box(766));
+  avl = gpr_avl_add(avl, box(180), box(765), NULL);
+  avl = gpr_avl_add(avl, box(319), box(766), NULL);
   avl = remove_int(avl, 92);
-  avl = gpr_avl_add(avl, box(483), box(768));
+  avl = gpr_avl_add(avl, box(483), box(768), NULL);
   avl = remove_int(avl, 504);
   avl = remove_int(avl, 1017);
   avl = remove_int(avl, 37);
   avl = remove_int(avl, 50);
-  avl = gpr_avl_add(avl, box(302), box(773));
+  avl = gpr_avl_add(avl, box(302), box(773), NULL);
   avl = remove_int(avl, 807);
-  avl = gpr_avl_add(avl, box(463), box(775));
-  avl = gpr_avl_add(avl, box(271), box(776));
-  avl = gpr_avl_add(avl, box(644), box(777));
+  avl = gpr_avl_add(avl, box(463), box(775), NULL);
+  avl = gpr_avl_add(avl, box(271), box(776), NULL);
+  avl = gpr_avl_add(avl, box(644), box(777), NULL);
   avl = remove_int(avl, 618);
-  avl = gpr_avl_add(avl, box(166), box(779));
-  avl = gpr_avl_add(avl, box(538), box(780));
+  avl = gpr_avl_add(avl, box(166), box(779), NULL);
+  avl = gpr_avl_add(avl, box(538), box(780), NULL);
   avl = remove_int(avl, 606);
-  avl = gpr_avl_add(avl, box(425), box(782));
+  avl = gpr_avl_add(avl, box(425), box(782), NULL);
   avl = remove_int(avl, 725);
   avl = remove_int(avl, 383);
-  avl = gpr_avl_add(avl, box(155), box(785));
+  avl = gpr_avl_add(avl, box(155), box(785), NULL);
   avl = remove_int(avl, 889);
-  avl = gpr_avl_add(avl, box(653), box(787));
+  avl = gpr_avl_add(avl, box(653), box(787), NULL);
   avl = remove_int(avl, 386);
-  avl = gpr_avl_add(avl, box(142), box(789));
+  avl = gpr_avl_add(avl, box(142), box(789), NULL);
   avl = remove_int(avl, 107);
   avl = remove_int(avl, 603);
   avl = remove_int(avl, 971);
-  avl = gpr_avl_add(avl, box(80), box(793));
-  avl = gpr_avl_add(avl, box(61), box(794));
-  avl = gpr_avl_add(avl, box(693), box(795));
-  avl = gpr_avl_add(avl, box(592), box(796));
-  avl = gpr_avl_add(avl, box(433), box(797));
-  avl = gpr_avl_add(avl, box(973), box(798));
+  avl = gpr_avl_add(avl, box(80), box(793), NULL);
+  avl = gpr_avl_add(avl, box(61), box(794), NULL);
+  avl = gpr_avl_add(avl, box(693), box(795), NULL);
+  avl = gpr_avl_add(avl, box(592), box(796), NULL);
+  avl = gpr_avl_add(avl, box(433), box(797), NULL);
+  avl = gpr_avl_add(avl, box(973), box(798), NULL);
   avl = remove_int(avl, 901);
   avl = remove_int(avl, 340);
   avl = remove_int(avl, 709);
-  avl = gpr_avl_add(avl, box(224), box(802));
+  avl = gpr_avl_add(avl, box(224), box(802), NULL);
   avl = remove_int(avl, 120);
   avl = remove_int(avl, 271);
-  avl = gpr_avl_add(avl, box(780), box(805));
-  avl = gpr_avl_add(avl, box(867), box(806));
-  avl = gpr_avl_add(avl, box(756), box(807));
-  avl = gpr_avl_add(avl, box(583), box(808));
-  avl = gpr_avl_add(avl, box(356), box(809));
-  avl = gpr_avl_add(avl, box(58), box(810));
+  avl = gpr_avl_add(avl, box(780), box(805), NULL);
+  avl = gpr_avl_add(avl, box(867), box(806), NULL);
+  avl = gpr_avl_add(avl, box(756), box(807), NULL);
+  avl = gpr_avl_add(avl, box(583), box(808), NULL);
+  avl = gpr_avl_add(avl, box(356), box(809), NULL);
+  avl = gpr_avl_add(avl, box(58), box(810), NULL);
   avl = remove_int(avl, 219);
-  avl = gpr_avl_add(avl, box(301), box(812));
+  avl = gpr_avl_add(avl, box(301), box(812), NULL);
   avl = remove_int(avl, 643);
   avl = remove_int(avl, 787);
   avl = remove_int(avl, 583);
@@ -1063,72 +1065,72 @@
   avl = remove_int(avl, 608);
   avl = remove_int(avl, 363);
   avl = remove_int(avl, 690);
-  avl = gpr_avl_add(avl, box(233), box(821));
-  avl = gpr_avl_add(avl, box(479), box(822));
-  avl = gpr_avl_add(avl, box(323), box(823));
-  avl = gpr_avl_add(avl, box(802), box(824));
+  avl = gpr_avl_add(avl, box(233), box(821), NULL);
+  avl = gpr_avl_add(avl, box(479), box(822), NULL);
+  avl = gpr_avl_add(avl, box(323), box(823), NULL);
+  avl = gpr_avl_add(avl, box(802), box(824), NULL);
   avl = remove_int(avl, 682);
   avl = remove_int(avl, 705);
   avl = remove_int(avl, 487);
-  avl = gpr_avl_add(avl, box(530), box(828));
-  avl = gpr_avl_add(avl, box(232), box(829));
+  avl = gpr_avl_add(avl, box(530), box(828), NULL);
+  avl = gpr_avl_add(avl, box(232), box(829), NULL);
   avl = remove_int(avl, 627);
-  avl = gpr_avl_add(avl, box(396), box(831));
-  avl = gpr_avl_add(avl, box(61), box(832));
-  avl = gpr_avl_add(avl, box(932), box(833));
-  avl = gpr_avl_add(avl, box(108), box(834));
-  avl = gpr_avl_add(avl, box(524), box(835));
+  avl = gpr_avl_add(avl, box(396), box(831), NULL);
+  avl = gpr_avl_add(avl, box(61), box(832), NULL);
+  avl = gpr_avl_add(avl, box(932), box(833), NULL);
+  avl = gpr_avl_add(avl, box(108), box(834), NULL);
+  avl = gpr_avl_add(avl, box(524), box(835), NULL);
   avl = remove_int(avl, 390);
   avl = remove_int(avl, 307);
-  avl = gpr_avl_add(avl, box(722), box(838));
-  avl = gpr_avl_add(avl, box(907), box(839));
+  avl = gpr_avl_add(avl, box(722), box(838), NULL);
+  avl = gpr_avl_add(avl, box(907), box(839), NULL);
   avl = remove_int(avl, 286);
   avl = remove_int(avl, 337);
   avl = remove_int(avl, 443);
-  avl = gpr_avl_add(avl, box(973), box(843));
+  avl = gpr_avl_add(avl, box(973), box(843), NULL);
   avl = remove_int(avl, 930);
   avl = remove_int(avl, 242);
-  avl = gpr_avl_add(avl, box(997), box(846));
-  avl = gpr_avl_add(avl, box(689), box(847));
+  avl = gpr_avl_add(avl, box(997), box(846), NULL);
+  avl = gpr_avl_add(avl, box(689), box(847), NULL);
   avl = remove_int(avl, 318);
-  avl = gpr_avl_add(avl, box(703), box(849));
-  avl = gpr_avl_add(avl, box(868), box(850));
-  avl = gpr_avl_add(avl, box(200), box(851));
-  avl = gpr_avl_add(avl, box(960), box(852));
-  avl = gpr_avl_add(avl, box(80), box(853));
+  avl = gpr_avl_add(avl, box(703), box(849), NULL);
+  avl = gpr_avl_add(avl, box(868), box(850), NULL);
+  avl = gpr_avl_add(avl, box(200), box(851), NULL);
+  avl = gpr_avl_add(avl, box(960), box(852), NULL);
+  avl = gpr_avl_add(avl, box(80), box(853), NULL);
   avl = remove_int(avl, 113);
-  avl = gpr_avl_add(avl, box(135), box(855));
+  avl = gpr_avl_add(avl, box(135), box(855), NULL);
   avl = remove_int(avl, 529);
-  avl = gpr_avl_add(avl, box(366), box(857));
+  avl = gpr_avl_add(avl, box(366), box(857), NULL);
   avl = remove_int(avl, 272);
-  avl = gpr_avl_add(avl, box(921), box(859));
+  avl = gpr_avl_add(avl, box(921), box(859), NULL);
   avl = remove_int(avl, 497);
-  avl = gpr_avl_add(avl, box(712), box(861));
+  avl = gpr_avl_add(avl, box(712), box(861), NULL);
   avl = remove_int(avl, 777);
   avl = remove_int(avl, 505);
   avl = remove_int(avl, 974);
   avl = remove_int(avl, 497);
-  avl = gpr_avl_add(avl, box(388), box(866));
-  avl = gpr_avl_add(avl, box(29), box(867));
-  avl = gpr_avl_add(avl, box(180), box(868));
-  avl = gpr_avl_add(avl, box(983), box(869));
-  avl = gpr_avl_add(avl, box(72), box(870));
-  avl = gpr_avl_add(avl, box(693), box(871));
-  avl = gpr_avl_add(avl, box(567), box(872));
+  avl = gpr_avl_add(avl, box(388), box(866), NULL);
+  avl = gpr_avl_add(avl, box(29), box(867), NULL);
+  avl = gpr_avl_add(avl, box(180), box(868), NULL);
+  avl = gpr_avl_add(avl, box(983), box(869), NULL);
+  avl = gpr_avl_add(avl, box(72), box(870), NULL);
+  avl = gpr_avl_add(avl, box(693), box(871), NULL);
+  avl = gpr_avl_add(avl, box(567), box(872), NULL);
   avl = remove_int(avl, 549);
   avl = remove_int(avl, 351);
-  avl = gpr_avl_add(avl, box(1019), box(875));
+  avl = gpr_avl_add(avl, box(1019), box(875), NULL);
   avl = remove_int(avl, 585);
   avl = remove_int(avl, 294);
   avl = remove_int(avl, 61);
-  avl = gpr_avl_add(avl, box(409), box(879));
-  avl = gpr_avl_add(avl, box(984), box(880));
-  avl = gpr_avl_add(avl, box(830), box(881));
+  avl = gpr_avl_add(avl, box(409), box(879), NULL);
+  avl = gpr_avl_add(avl, box(984), box(880), NULL);
+  avl = gpr_avl_add(avl, box(830), box(881), NULL);
   avl = remove_int(avl, 579);
-  avl = gpr_avl_add(avl, box(672), box(883));
+  avl = gpr_avl_add(avl, box(672), box(883), NULL);
   avl = remove_int(avl, 968);
 
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_badcase3(void) {
@@ -1138,191 +1140,191 @@
 
   avl = gpr_avl_create(&int_int_vtable);
   avl = remove_int(avl, 624);
-  avl = gpr_avl_add(avl, box(59), box(2));
-  avl = gpr_avl_add(avl, box(494), box(3));
-  avl = gpr_avl_add(avl, box(226), box(4));
+  avl = gpr_avl_add(avl, box(59), box(2), NULL);
+  avl = gpr_avl_add(avl, box(494), box(3), NULL);
+  avl = gpr_avl_add(avl, box(226), box(4), NULL);
   avl = remove_int(avl, 524);
-  avl = gpr_avl_add(avl, box(540), box(6));
+  avl = gpr_avl_add(avl, box(540), box(6), NULL);
   avl = remove_int(avl, 1008);
-  avl = gpr_avl_add(avl, box(502), box(8));
+  avl = gpr_avl_add(avl, box(502), box(8), NULL);
   avl = remove_int(avl, 267);
   avl = remove_int(avl, 764);
   avl = remove_int(avl, 443);
-  avl = gpr_avl_add(avl, box(8), box(12));
+  avl = gpr_avl_add(avl, box(8), box(12), NULL);
   avl = remove_int(avl, 291);
   avl = remove_int(avl, 796);
   avl = remove_int(avl, 1002);
-  avl = gpr_avl_add(avl, box(778), box(16));
+  avl = gpr_avl_add(avl, box(778), box(16), NULL);
   avl = remove_int(avl, 621);
   avl = remove_int(avl, 891);
   avl = remove_int(avl, 880);
-  avl = gpr_avl_add(avl, box(197), box(20));
-  avl = gpr_avl_add(avl, box(441), box(21));
-  avl = gpr_avl_add(avl, box(719), box(22));
+  avl = gpr_avl_add(avl, box(197), box(20), NULL);
+  avl = gpr_avl_add(avl, box(441), box(21), NULL);
+  avl = gpr_avl_add(avl, box(719), box(22), NULL);
   avl = remove_int(avl, 109);
-  avl = gpr_avl_add(avl, box(458), box(24));
+  avl = gpr_avl_add(avl, box(458), box(24), NULL);
   avl = remove_int(avl, 86);
-  avl = gpr_avl_add(avl, box(897), box(26));
-  avl = gpr_avl_add(avl, box(997), box(27));
+  avl = gpr_avl_add(avl, box(897), box(26), NULL);
+  avl = gpr_avl_add(avl, box(997), box(27), NULL);
   avl = remove_int(avl, 235);
   avl = remove_int(avl, 425);
   avl = remove_int(avl, 186);
-  avl = gpr_avl_add(avl, box(887), box(31));
-  avl = gpr_avl_add(avl, box(1005), box(32));
-  avl = gpr_avl_add(avl, box(778), box(33));
-  avl = gpr_avl_add(avl, box(575), box(34));
+  avl = gpr_avl_add(avl, box(887), box(31), NULL);
+  avl = gpr_avl_add(avl, box(1005), box(32), NULL);
+  avl = gpr_avl_add(avl, box(778), box(33), NULL);
+  avl = gpr_avl_add(avl, box(575), box(34), NULL);
   avl = remove_int(avl, 966);
   avl = remove_int(avl, 1015);
-  avl = gpr_avl_add(avl, box(486), box(37));
-  avl = gpr_avl_add(avl, box(809), box(38));
-  avl = gpr_avl_add(avl, box(907), box(39));
-  avl = gpr_avl_add(avl, box(971), box(40));
+  avl = gpr_avl_add(avl, box(486), box(37), NULL);
+  avl = gpr_avl_add(avl, box(809), box(38), NULL);
+  avl = gpr_avl_add(avl, box(907), box(39), NULL);
+  avl = gpr_avl_add(avl, box(971), box(40), NULL);
   avl = remove_int(avl, 441);
   avl = remove_int(avl, 498);
-  avl = gpr_avl_add(avl, box(727), box(43));
+  avl = gpr_avl_add(avl, box(727), box(43), NULL);
   avl = remove_int(avl, 679);
   avl = remove_int(avl, 740);
   avl = remove_int(avl, 532);
-  avl = gpr_avl_add(avl, box(805), box(47));
+  avl = gpr_avl_add(avl, box(805), box(47), NULL);
   avl = remove_int(avl, 64);
-  avl = gpr_avl_add(avl, box(362), box(49));
-  avl = gpr_avl_add(avl, box(170), box(50));
-  avl = gpr_avl_add(avl, box(389), box(51));
-  avl = gpr_avl_add(avl, box(689), box(52));
+  avl = gpr_avl_add(avl, box(362), box(49), NULL);
+  avl = gpr_avl_add(avl, box(170), box(50), NULL);
+  avl = gpr_avl_add(avl, box(389), box(51), NULL);
+  avl = gpr_avl_add(avl, box(689), box(52), NULL);
   avl = remove_int(avl, 871);
-  avl = gpr_avl_add(avl, box(447), box(54));
+  avl = gpr_avl_add(avl, box(447), box(54), NULL);
   avl = remove_int(avl, 718);
-  avl = gpr_avl_add(avl, box(724), box(56));
+  avl = gpr_avl_add(avl, box(724), box(56), NULL);
   avl = remove_int(avl, 215);
-  avl = gpr_avl_add(avl, box(550), box(58));
+  avl = gpr_avl_add(avl, box(550), box(58), NULL);
   avl = remove_int(avl, 932);
-  avl = gpr_avl_add(avl, box(47), box(60));
+  avl = gpr_avl_add(avl, box(47), box(60), NULL);
   avl = remove_int(avl, 46);
   avl = remove_int(avl, 229);
-  avl = gpr_avl_add(avl, box(68), box(63));
-  avl = gpr_avl_add(avl, box(387), box(64));
+  avl = gpr_avl_add(avl, box(68), box(63), NULL);
+  avl = gpr_avl_add(avl, box(387), box(64), NULL);
   avl = remove_int(avl, 933);
   avl = remove_int(avl, 736);
   avl = remove_int(avl, 719);
-  avl = gpr_avl_add(avl, box(150), box(68));
+  avl = gpr_avl_add(avl, box(150), box(68), NULL);
   avl = remove_int(avl, 875);
   avl = remove_int(avl, 298);
-  avl = gpr_avl_add(avl, box(991), box(71));
+  avl = gpr_avl_add(avl, box(991), box(71), NULL);
   avl = remove_int(avl, 705);
-  avl = gpr_avl_add(avl, box(197), box(73));
-  avl = gpr_avl_add(avl, box(101), box(74));
+  avl = gpr_avl_add(avl, box(197), box(73), NULL);
+  avl = gpr_avl_add(avl, box(101), box(74), NULL);
   avl = remove_int(avl, 436);
-  avl = gpr_avl_add(avl, box(755), box(76));
-  avl = gpr_avl_add(avl, box(727), box(77));
+  avl = gpr_avl_add(avl, box(755), box(76), NULL);
+  avl = gpr_avl_add(avl, box(727), box(77), NULL);
   avl = remove_int(avl, 309);
   avl = remove_int(avl, 253);
-  avl = gpr_avl_add(avl, box(203), box(80));
+  avl = gpr_avl_add(avl, box(203), box(80), NULL);
   avl = remove_int(avl, 231);
-  avl = gpr_avl_add(avl, box(461), box(82));
+  avl = gpr_avl_add(avl, box(461), box(82), NULL);
   avl = remove_int(avl, 316);
   avl = remove_int(avl, 493);
-  avl = gpr_avl_add(avl, box(184), box(85));
+  avl = gpr_avl_add(avl, box(184), box(85), NULL);
   avl = remove_int(avl, 737);
-  avl = gpr_avl_add(avl, box(790), box(87));
-  avl = gpr_avl_add(avl, box(335), box(88));
+  avl = gpr_avl_add(avl, box(790), box(87), NULL);
+  avl = gpr_avl_add(avl, box(335), box(88), NULL);
   avl = remove_int(avl, 649);
-  avl = gpr_avl_add(avl, box(69), box(90));
+  avl = gpr_avl_add(avl, box(69), box(90), NULL);
   avl = remove_int(avl, 585);
   avl = remove_int(avl, 543);
-  avl = gpr_avl_add(avl, box(784), box(93));
-  avl = gpr_avl_add(avl, box(60), box(94));
-  avl = gpr_avl_add(avl, box(525), box(95));
-  avl = gpr_avl_add(avl, box(177), box(96));
-  avl = gpr_avl_add(avl, box(178), box(97));
-  avl = gpr_avl_add(avl, box(683), box(98));
-  avl = gpr_avl_add(avl, box(226), box(99));
-  avl = gpr_avl_add(avl, box(662), box(100));
+  avl = gpr_avl_add(avl, box(784), box(93), NULL);
+  avl = gpr_avl_add(avl, box(60), box(94), NULL);
+  avl = gpr_avl_add(avl, box(525), box(95), NULL);
+  avl = gpr_avl_add(avl, box(177), box(96), NULL);
+  avl = gpr_avl_add(avl, box(178), box(97), NULL);
+  avl = gpr_avl_add(avl, box(683), box(98), NULL);
+  avl = gpr_avl_add(avl, box(226), box(99), NULL);
+  avl = gpr_avl_add(avl, box(662), box(100), NULL);
   avl = remove_int(avl, 944);
-  avl = gpr_avl_add(avl, box(562), box(102));
-  avl = gpr_avl_add(avl, box(793), box(103));
+  avl = gpr_avl_add(avl, box(562), box(102), NULL);
+  avl = gpr_avl_add(avl, box(793), box(103), NULL);
   avl = remove_int(avl, 673);
-  avl = gpr_avl_add(avl, box(310), box(105));
+  avl = gpr_avl_add(avl, box(310), box(105), NULL);
   avl = remove_int(avl, 479);
   avl = remove_int(avl, 543);
   avl = remove_int(avl, 159);
   avl = remove_int(avl, 850);
-  avl = gpr_avl_add(avl, box(318), box(110));
-  avl = gpr_avl_add(avl, box(483), box(111));
-  avl = gpr_avl_add(avl, box(84), box(112));
+  avl = gpr_avl_add(avl, box(318), box(110), NULL);
+  avl = gpr_avl_add(avl, box(483), box(111), NULL);
+  avl = gpr_avl_add(avl, box(84), box(112), NULL);
   avl = remove_int(avl, 109);
-  avl = gpr_avl_add(avl, box(132), box(114));
-  avl = gpr_avl_add(avl, box(920), box(115));
+  avl = gpr_avl_add(avl, box(132), box(114), NULL);
+  avl = gpr_avl_add(avl, box(920), box(115), NULL);
   avl = remove_int(avl, 746);
-  avl = gpr_avl_add(avl, box(145), box(117));
-  avl = gpr_avl_add(avl, box(526), box(118));
+  avl = gpr_avl_add(avl, box(145), box(117), NULL);
+  avl = gpr_avl_add(avl, box(526), box(118), NULL);
   avl = remove_int(avl, 158);
-  avl = gpr_avl_add(avl, box(332), box(120));
-  avl = gpr_avl_add(avl, box(918), box(121));
+  avl = gpr_avl_add(avl, box(332), box(120), NULL);
+  avl = gpr_avl_add(avl, box(918), box(121), NULL);
   avl = remove_int(avl, 339);
-  avl = gpr_avl_add(avl, box(809), box(123));
-  avl = gpr_avl_add(avl, box(742), box(124));
-  avl = gpr_avl_add(avl, box(718), box(125));
+  avl = gpr_avl_add(avl, box(809), box(123), NULL);
+  avl = gpr_avl_add(avl, box(742), box(124), NULL);
+  avl = gpr_avl_add(avl, box(718), box(125), NULL);
   avl = remove_int(avl, 988);
   avl = remove_int(avl, 531);
   avl = remove_int(avl, 840);
-  avl = gpr_avl_add(avl, box(816), box(129));
-  avl = gpr_avl_add(avl, box(976), box(130));
+  avl = gpr_avl_add(avl, box(816), box(129), NULL);
+  avl = gpr_avl_add(avl, box(976), box(130), NULL);
   avl = remove_int(avl, 743);
   avl = remove_int(avl, 528);
   avl = remove_int(avl, 982);
-  avl = gpr_avl_add(avl, box(803), box(134));
-  avl = gpr_avl_add(avl, box(205), box(135));
-  avl = gpr_avl_add(avl, box(584), box(136));
+  avl = gpr_avl_add(avl, box(803), box(134), NULL);
+  avl = gpr_avl_add(avl, box(205), box(135), NULL);
+  avl = gpr_avl_add(avl, box(584), box(136), NULL);
   avl = remove_int(avl, 923);
   avl = remove_int(avl, 538);
   avl = remove_int(avl, 398);
   avl = remove_int(avl, 320);
   avl = remove_int(avl, 292);
-  avl = gpr_avl_add(avl, box(270), box(142));
-  avl = gpr_avl_add(avl, box(333), box(143));
+  avl = gpr_avl_add(avl, box(270), box(142), NULL);
+  avl = gpr_avl_add(avl, box(333), box(143), NULL);
   avl = remove_int(avl, 439);
-  avl = gpr_avl_add(avl, box(35), box(145));
-  avl = gpr_avl_add(avl, box(837), box(146));
+  avl = gpr_avl_add(avl, box(35), box(145), NULL);
+  avl = gpr_avl_add(avl, box(837), box(146), NULL);
   avl = remove_int(avl, 65);
   avl = remove_int(avl, 642);
   avl = remove_int(avl, 371);
   avl = remove_int(avl, 140);
   avl = remove_int(avl, 533);
   avl = remove_int(avl, 676);
-  avl = gpr_avl_add(avl, box(624), box(153));
-  avl = gpr_avl_add(avl, box(116), box(154));
-  avl = gpr_avl_add(avl, box(446), box(155));
+  avl = gpr_avl_add(avl, box(624), box(153), NULL);
+  avl = gpr_avl_add(avl, box(116), box(154), NULL);
+  avl = gpr_avl_add(avl, box(446), box(155), NULL);
   avl = remove_int(avl, 91);
   avl = remove_int(avl, 721);
   avl = remove_int(avl, 537);
-  avl = gpr_avl_add(avl, box(448), box(159));
+  avl = gpr_avl_add(avl, box(448), box(159), NULL);
   avl = remove_int(avl, 155);
   avl = remove_int(avl, 344);
   avl = remove_int(avl, 237);
-  avl = gpr_avl_add(avl, box(309), box(163));
-  avl = gpr_avl_add(avl, box(434), box(164));
-  avl = gpr_avl_add(avl, box(277), box(165));
+  avl = gpr_avl_add(avl, box(309), box(163), NULL);
+  avl = gpr_avl_add(avl, box(434), box(164), NULL);
+  avl = gpr_avl_add(avl, box(277), box(165), NULL);
   avl = remove_int(avl, 233);
-  avl = gpr_avl_add(avl, box(275), box(167));
-  avl = gpr_avl_add(avl, box(218), box(168));
-  avl = gpr_avl_add(avl, box(76), box(169));
-  avl = gpr_avl_add(avl, box(898), box(170));
+  avl = gpr_avl_add(avl, box(275), box(167), NULL);
+  avl = gpr_avl_add(avl, box(218), box(168), NULL);
+  avl = gpr_avl_add(avl, box(76), box(169), NULL);
+  avl = gpr_avl_add(avl, box(898), box(170), NULL);
   avl = remove_int(avl, 771);
-  avl = gpr_avl_add(avl, box(237), box(172));
+  avl = gpr_avl_add(avl, box(237), box(172), NULL);
   avl = remove_int(avl, 327);
-  avl = gpr_avl_add(avl, box(499), box(174));
+  avl = gpr_avl_add(avl, box(499), box(174), NULL);
   avl = remove_int(avl, 727);
   avl = remove_int(avl, 234);
   avl = remove_int(avl, 623);
   avl = remove_int(avl, 458);
   avl = remove_int(avl, 326);
   avl = remove_int(avl, 589);
-  avl = gpr_avl_add(avl, box(442), box(181));
+  avl = gpr_avl_add(avl, box(442), box(181), NULL);
   avl = remove_int(avl, 389);
-  avl = gpr_avl_add(avl, box(708), box(183));
-  avl = gpr_avl_add(avl, box(594), box(184));
-  avl = gpr_avl_add(avl, box(942), box(185));
-  avl = gpr_avl_add(avl, box(282), box(186));
+  avl = gpr_avl_add(avl, box(708), box(183), NULL);
+  avl = gpr_avl_add(avl, box(594), box(184), NULL);
+  avl = gpr_avl_add(avl, box(942), box(185), NULL);
+  avl = gpr_avl_add(avl, box(282), box(186), NULL);
   avl = remove_int(avl, 434);
   avl = remove_int(avl, 134);
   avl = remove_int(avl, 270);
@@ -1332,125 +1334,125 @@
   avl = remove_int(avl, 193);
   avl = remove_int(avl, 797);
   avl = remove_int(avl, 347);
-  avl = gpr_avl_add(avl, box(99), box(196));
-  avl = gpr_avl_add(avl, box(161), box(197));
+  avl = gpr_avl_add(avl, box(99), box(196), NULL);
+  avl = gpr_avl_add(avl, box(161), box(197), NULL);
   avl = remove_int(avl, 484);
-  avl = gpr_avl_add(avl, box(72), box(199));
+  avl = gpr_avl_add(avl, box(72), box(199), NULL);
   avl = remove_int(avl, 629);
-  avl = gpr_avl_add(avl, box(522), box(201));
+  avl = gpr_avl_add(avl, box(522), box(201), NULL);
   avl = remove_int(avl, 679);
-  avl = gpr_avl_add(avl, box(407), box(203));
+  avl = gpr_avl_add(avl, box(407), box(203), NULL);
   avl = remove_int(avl, 693);
-  avl = gpr_avl_add(avl, box(424), box(205));
-  avl = gpr_avl_add(avl, box(651), box(206));
-  avl = gpr_avl_add(avl, box(927), box(207));
+  avl = gpr_avl_add(avl, box(424), box(205), NULL);
+  avl = gpr_avl_add(avl, box(651), box(206), NULL);
+  avl = gpr_avl_add(avl, box(927), box(207), NULL);
   avl = remove_int(avl, 553);
-  avl = gpr_avl_add(avl, box(128), box(209));
-  avl = gpr_avl_add(avl, box(616), box(210));
-  avl = gpr_avl_add(avl, box(690), box(211));
+  avl = gpr_avl_add(avl, box(128), box(209), NULL);
+  avl = gpr_avl_add(avl, box(616), box(210), NULL);
+  avl = gpr_avl_add(avl, box(690), box(211), NULL);
   avl = remove_int(avl, 241);
   avl = remove_int(avl, 179);
-  avl = gpr_avl_add(avl, box(697), box(214));
+  avl = gpr_avl_add(avl, box(697), box(214), NULL);
   avl = remove_int(avl, 779);
-  avl = gpr_avl_add(avl, box(241), box(216));
+  avl = gpr_avl_add(avl, box(241), box(216), NULL);
   avl = remove_int(avl, 190);
   avl = remove_int(avl, 210);
-  avl = gpr_avl_add(avl, box(711), box(219));
+  avl = gpr_avl_add(avl, box(711), box(219), NULL);
   avl = remove_int(avl, 251);
   avl = remove_int(avl, 61);
-  avl = gpr_avl_add(avl, box(800), box(222));
+  avl = gpr_avl_add(avl, box(800), box(222), NULL);
   avl = remove_int(avl, 551);
-  avl = gpr_avl_add(avl, box(61), box(224));
-  avl = gpr_avl_add(avl, box(656), box(225));
+  avl = gpr_avl_add(avl, box(61), box(224), NULL);
+  avl = gpr_avl_add(avl, box(656), box(225), NULL);
   avl = remove_int(avl, 130);
   avl = remove_int(avl, 368);
   avl = remove_int(avl, 150);
   avl = remove_int(avl, 73);
-  avl = gpr_avl_add(avl, box(799), box(230));
-  avl = gpr_avl_add(avl, box(125), box(231));
+  avl = gpr_avl_add(avl, box(799), box(230), NULL);
+  avl = gpr_avl_add(avl, box(125), box(231), NULL);
   avl = remove_int(avl, 107);
-  avl = gpr_avl_add(avl, box(938), box(233));
-  avl = gpr_avl_add(avl, box(914), box(234));
-  avl = gpr_avl_add(avl, box(197), box(235));
+  avl = gpr_avl_add(avl, box(938), box(233), NULL);
+  avl = gpr_avl_add(avl, box(914), box(234), NULL);
+  avl = gpr_avl_add(avl, box(197), box(235), NULL);
   avl = remove_int(avl, 736);
-  avl = gpr_avl_add(avl, box(20), box(237));
+  avl = gpr_avl_add(avl, box(20), box(237), NULL);
   avl = remove_int(avl, 224);
   avl = remove_int(avl, 841);
-  avl = gpr_avl_add(avl, box(226), box(240));
+  avl = gpr_avl_add(avl, box(226), box(240), NULL);
   avl = remove_int(avl, 963);
   avl = remove_int(avl, 796);
   avl = remove_int(avl, 728);
-  avl = gpr_avl_add(avl, box(855), box(244));
-  avl = gpr_avl_add(avl, box(769), box(245));
-  avl = gpr_avl_add(avl, box(631), box(246));
+  avl = gpr_avl_add(avl, box(855), box(244), NULL);
+  avl = gpr_avl_add(avl, box(769), box(245), NULL);
+  avl = gpr_avl_add(avl, box(631), box(246), NULL);
   avl = remove_int(avl, 648);
-  avl = gpr_avl_add(avl, box(187), box(248));
-  avl = gpr_avl_add(avl, box(31), box(249));
+  avl = gpr_avl_add(avl, box(187), box(248), NULL);
+  avl = gpr_avl_add(avl, box(31), box(249), NULL);
   avl = remove_int(avl, 163);
-  avl = gpr_avl_add(avl, box(218), box(251));
-  avl = gpr_avl_add(avl, box(488), box(252));
-  avl = gpr_avl_add(avl, box(387), box(253));
-  avl = gpr_avl_add(avl, box(809), box(254));
-  avl = gpr_avl_add(avl, box(997), box(255));
+  avl = gpr_avl_add(avl, box(218), box(251), NULL);
+  avl = gpr_avl_add(avl, box(488), box(252), NULL);
+  avl = gpr_avl_add(avl, box(387), box(253), NULL);
+  avl = gpr_avl_add(avl, box(809), box(254), NULL);
+  avl = gpr_avl_add(avl, box(997), box(255), NULL);
   avl = remove_int(avl, 678);
-  avl = gpr_avl_add(avl, box(368), box(257));
-  avl = gpr_avl_add(avl, box(220), box(258));
-  avl = gpr_avl_add(avl, box(373), box(259));
+  avl = gpr_avl_add(avl, box(368), box(257), NULL);
+  avl = gpr_avl_add(avl, box(220), box(258), NULL);
+  avl = gpr_avl_add(avl, box(373), box(259), NULL);
   avl = remove_int(avl, 874);
   avl = remove_int(avl, 682);
   avl = remove_int(avl, 1014);
   avl = remove_int(avl, 195);
-  avl = gpr_avl_add(avl, box(868), box(264));
+  avl = gpr_avl_add(avl, box(868), box(264), NULL);
   avl = remove_int(avl, 254);
   avl = remove_int(avl, 456);
-  avl = gpr_avl_add(avl, box(906), box(267));
+  avl = gpr_avl_add(avl, box(906), box(267), NULL);
   avl = remove_int(avl, 711);
-  avl = gpr_avl_add(avl, box(632), box(269));
+  avl = gpr_avl_add(avl, box(632), box(269), NULL);
   avl = remove_int(avl, 474);
-  avl = gpr_avl_add(avl, box(508), box(271));
-  avl = gpr_avl_add(avl, box(518), box(272));
+  avl = gpr_avl_add(avl, box(508), box(271), NULL);
+  avl = gpr_avl_add(avl, box(518), box(272), NULL);
   avl = remove_int(avl, 579);
   avl = remove_int(avl, 948);
-  avl = gpr_avl_add(avl, box(789), box(275));
-  avl = gpr_avl_add(avl, box(48), box(276));
-  avl = gpr_avl_add(avl, box(256), box(277));
-  avl = gpr_avl_add(avl, box(754), box(278));
+  avl = gpr_avl_add(avl, box(789), box(275), NULL);
+  avl = gpr_avl_add(avl, box(48), box(276), NULL);
+  avl = gpr_avl_add(avl, box(256), box(277), NULL);
+  avl = gpr_avl_add(avl, box(754), box(278), NULL);
   avl = remove_int(avl, 215);
-  avl = gpr_avl_add(avl, box(679), box(280));
-  avl = gpr_avl_add(avl, box(606), box(281));
+  avl = gpr_avl_add(avl, box(679), box(280), NULL);
+  avl = gpr_avl_add(avl, box(606), box(281), NULL);
   avl = remove_int(avl, 941);
   avl = remove_int(avl, 31);
-  avl = gpr_avl_add(avl, box(758), box(284));
+  avl = gpr_avl_add(avl, box(758), box(284), NULL);
   avl = remove_int(avl, 101);
-  avl = gpr_avl_add(avl, box(244), box(286));
-  avl = gpr_avl_add(avl, box(337), box(287));
-  avl = gpr_avl_add(avl, box(461), box(288));
+  avl = gpr_avl_add(avl, box(244), box(286), NULL);
+  avl = gpr_avl_add(avl, box(337), box(287), NULL);
+  avl = gpr_avl_add(avl, box(461), box(288), NULL);
   avl = remove_int(avl, 476);
-  avl = gpr_avl_add(avl, box(845), box(290));
+  avl = gpr_avl_add(avl, box(845), box(290), NULL);
   avl = remove_int(avl, 160);
-  avl = gpr_avl_add(avl, box(690), box(292));
+  avl = gpr_avl_add(avl, box(690), box(292), NULL);
   avl = remove_int(avl, 931);
-  avl = gpr_avl_add(avl, box(869), box(294));
-  avl = gpr_avl_add(avl, box(1019), box(295));
+  avl = gpr_avl_add(avl, box(869), box(294), NULL);
+  avl = gpr_avl_add(avl, box(1019), box(295), NULL);
   avl = remove_int(avl, 591);
   avl = remove_int(avl, 635);
   avl = remove_int(avl, 67);
-  avl = gpr_avl_add(avl, box(113), box(299));
+  avl = gpr_avl_add(avl, box(113), box(299), NULL);
   avl = remove_int(avl, 305);
-  avl = gpr_avl_add(avl, box(10), box(301));
+  avl = gpr_avl_add(avl, box(10), box(301), NULL);
   avl = remove_int(avl, 823);
   avl = remove_int(avl, 288);
   avl = remove_int(avl, 239);
-  avl = gpr_avl_add(avl, box(646), box(305));
-  avl = gpr_avl_add(avl, box(1006), box(306));
-  avl = gpr_avl_add(avl, box(954), box(307));
-  avl = gpr_avl_add(avl, box(199), box(308));
-  avl = gpr_avl_add(avl, box(69), box(309));
-  avl = gpr_avl_add(avl, box(984), box(310));
+  avl = gpr_avl_add(avl, box(646), box(305), NULL);
+  avl = gpr_avl_add(avl, box(1006), box(306), NULL);
+  avl = gpr_avl_add(avl, box(954), box(307), NULL);
+  avl = gpr_avl_add(avl, box(199), box(308), NULL);
+  avl = gpr_avl_add(avl, box(69), box(309), NULL);
+  avl = gpr_avl_add(avl, box(984), box(310), NULL);
   avl = remove_int(avl, 568);
   avl = remove_int(avl, 666);
   avl = remove_int(avl, 37);
-  avl = gpr_avl_add(avl, box(845), box(314));
+  avl = gpr_avl_add(avl, box(845), box(314), NULL);
   avl = remove_int(avl, 535);
   avl = remove_int(avl, 365);
   avl = remove_int(avl, 676);
@@ -1458,372 +1460,372 @@
   avl = remove_int(avl, 425);
   avl = remove_int(avl, 704);
   avl = remove_int(avl, 168);
-  avl = gpr_avl_add(avl, box(853), box(322));
-  avl = gpr_avl_add(avl, box(335), box(323));
-  avl = gpr_avl_add(avl, box(961), box(324));
-  avl = gpr_avl_add(avl, box(73), box(325));
+  avl = gpr_avl_add(avl, box(853), box(322), NULL);
+  avl = gpr_avl_add(avl, box(335), box(323), NULL);
+  avl = gpr_avl_add(avl, box(961), box(324), NULL);
+  avl = gpr_avl_add(avl, box(73), box(325), NULL);
   avl = remove_int(avl, 469);
-  avl = gpr_avl_add(avl, box(449), box(327));
+  avl = gpr_avl_add(avl, box(449), box(327), NULL);
   avl = remove_int(avl, 821);
-  avl = gpr_avl_add(avl, box(845), box(329));
+  avl = gpr_avl_add(avl, box(845), box(329), NULL);
   avl = remove_int(avl, 637);
-  avl = gpr_avl_add(avl, box(769), box(331));
-  avl = gpr_avl_add(avl, box(901), box(332));
+  avl = gpr_avl_add(avl, box(769), box(331), NULL);
+  avl = gpr_avl_add(avl, box(901), box(332), NULL);
   avl = remove_int(avl, 142);
   avl = remove_int(avl, 361);
   avl = remove_int(avl, 876);
-  avl = gpr_avl_add(avl, box(614), box(336));
-  avl = gpr_avl_add(avl, box(729), box(337));
+  avl = gpr_avl_add(avl, box(614), box(336), NULL);
+  avl = gpr_avl_add(avl, box(729), box(337), NULL);
   avl = remove_int(avl, 120);
   avl = remove_int(avl, 473);
   avl = remove_int(avl, 445);
-  avl = gpr_avl_add(avl, box(978), box(341));
-  avl = gpr_avl_add(avl, box(164), box(342));
-  avl = gpr_avl_add(avl, box(1), box(343));
+  avl = gpr_avl_add(avl, box(978), box(341), NULL);
+  avl = gpr_avl_add(avl, box(164), box(342), NULL);
+  avl = gpr_avl_add(avl, box(1), box(343), NULL);
   avl = remove_int(avl, 890);
-  avl = gpr_avl_add(avl, box(605), box(345));
-  avl = gpr_avl_add(avl, box(178), box(346));
-  avl = gpr_avl_add(avl, box(481), box(347));
-  avl = gpr_avl_add(avl, box(772), box(348));
+  avl = gpr_avl_add(avl, box(605), box(345), NULL);
+  avl = gpr_avl_add(avl, box(178), box(346), NULL);
+  avl = gpr_avl_add(avl, box(481), box(347), NULL);
+  avl = gpr_avl_add(avl, box(772), box(348), NULL);
   avl = remove_int(avl, 824);
   avl = remove_int(avl, 167);
   avl = remove_int(avl, 151);
-  avl = gpr_avl_add(avl, box(698), box(352));
-  avl = gpr_avl_add(avl, box(202), box(353));
-  avl = gpr_avl_add(avl, box(921), box(354));
-  avl = gpr_avl_add(avl, box(875), box(355));
+  avl = gpr_avl_add(avl, box(698), box(352), NULL);
+  avl = gpr_avl_add(avl, box(202), box(353), NULL);
+  avl = gpr_avl_add(avl, box(921), box(354), NULL);
+  avl = gpr_avl_add(avl, box(875), box(355), NULL);
   avl = remove_int(avl, 197);
   avl = remove_int(avl, 232);
-  avl = gpr_avl_add(avl, box(209), box(358));
+  avl = gpr_avl_add(avl, box(209), box(358), NULL);
   avl = remove_int(avl, 324);
   avl = remove_int(avl, 56);
   avl = remove_int(avl, 579);
   avl = remove_int(avl, 255);
   avl = remove_int(avl, 290);
-  avl = gpr_avl_add(avl, box(661), box(364));
-  avl = gpr_avl_add(avl, box(113), box(365));
+  avl = gpr_avl_add(avl, box(661), box(364), NULL);
+  avl = gpr_avl_add(avl, box(113), box(365), NULL);
   avl = remove_int(avl, 767);
-  avl = gpr_avl_add(avl, box(586), box(367));
-  avl = gpr_avl_add(avl, box(121), box(368));
+  avl = gpr_avl_add(avl, box(586), box(367), NULL);
+  avl = gpr_avl_add(avl, box(121), box(368), NULL);
   avl = remove_int(avl, 235);
   avl = remove_int(avl, 439);
   avl = remove_int(avl, 360);
-  avl = gpr_avl_add(avl, box(916), box(372));
+  avl = gpr_avl_add(avl, box(916), box(372), NULL);
   avl = remove_int(avl, 999);
-  avl = gpr_avl_add(avl, box(825), box(374));
-  avl = gpr_avl_add(avl, box(177), box(375));
+  avl = gpr_avl_add(avl, box(825), box(374), NULL);
+  avl = gpr_avl_add(avl, box(177), box(375), NULL);
   avl = remove_int(avl, 204);
   avl = remove_int(avl, 92);
-  avl = gpr_avl_add(avl, box(794), box(378));
-  avl = gpr_avl_add(avl, box(463), box(379));
-  avl = gpr_avl_add(avl, box(472), box(380));
+  avl = gpr_avl_add(avl, box(794), box(378), NULL);
+  avl = gpr_avl_add(avl, box(463), box(379), NULL);
+  avl = gpr_avl_add(avl, box(472), box(380), NULL);
   avl = remove_int(avl, 235);
-  avl = gpr_avl_add(avl, box(840), box(382));
+  avl = gpr_avl_add(avl, box(840), box(382), NULL);
   avl = remove_int(avl, 657);
-  avl = gpr_avl_add(avl, box(586), box(384));
-  avl = gpr_avl_add(avl, box(979), box(385));
+  avl = gpr_avl_add(avl, box(586), box(384), NULL);
+  avl = gpr_avl_add(avl, box(979), box(385), NULL);
   avl = remove_int(avl, 979);
-  avl = gpr_avl_add(avl, box(639), box(387));
+  avl = gpr_avl_add(avl, box(639), box(387), NULL);
   avl = remove_int(avl, 907);
   avl = remove_int(avl, 973);
-  avl = gpr_avl_add(avl, box(913), box(390));
-  avl = gpr_avl_add(avl, box(566), box(391));
-  avl = gpr_avl_add(avl, box(883), box(392));
-  avl = gpr_avl_add(avl, box(552), box(393));
-  avl = gpr_avl_add(avl, box(16), box(394));
+  avl = gpr_avl_add(avl, box(913), box(390), NULL);
+  avl = gpr_avl_add(avl, box(566), box(391), NULL);
+  avl = gpr_avl_add(avl, box(883), box(392), NULL);
+  avl = gpr_avl_add(avl, box(552), box(393), NULL);
+  avl = gpr_avl_add(avl, box(16), box(394), NULL);
   avl = remove_int(avl, 60);
-  avl = gpr_avl_add(avl, box(567), box(396));
-  avl = gpr_avl_add(avl, box(705), box(397));
-  avl = gpr_avl_add(avl, box(94), box(398));
+  avl = gpr_avl_add(avl, box(567), box(396), NULL);
+  avl = gpr_avl_add(avl, box(705), box(397), NULL);
+  avl = gpr_avl_add(avl, box(94), box(398), NULL);
   avl = remove_int(avl, 321);
-  avl = gpr_avl_add(avl, box(207), box(400));
-  avl = gpr_avl_add(avl, box(682), box(401));
-  avl = gpr_avl_add(avl, box(592), box(402));
-  avl = gpr_avl_add(avl, box(10), box(403));
+  avl = gpr_avl_add(avl, box(207), box(400), NULL);
+  avl = gpr_avl_add(avl, box(682), box(401), NULL);
+  avl = gpr_avl_add(avl, box(592), box(402), NULL);
+  avl = gpr_avl_add(avl, box(10), box(403), NULL);
   avl = remove_int(avl, 911);
   avl = remove_int(avl, 161);
-  avl = gpr_avl_add(avl, box(86), box(406));
+  avl = gpr_avl_add(avl, box(86), box(406), NULL);
   avl = remove_int(avl, 893);
   avl = remove_int(avl, 362);
-  avl = gpr_avl_add(avl, box(599), box(409));
+  avl = gpr_avl_add(avl, box(599), box(409), NULL);
   avl = remove_int(avl, 413);
-  avl = gpr_avl_add(avl, box(867), box(411));
+  avl = gpr_avl_add(avl, box(867), box(411), NULL);
   avl = remove_int(avl, 955);
-  avl = gpr_avl_add(avl, box(341), box(413));
-  avl = gpr_avl_add(avl, box(887), box(414));
+  avl = gpr_avl_add(avl, box(341), box(413), NULL);
+  avl = gpr_avl_add(avl, box(887), box(414), NULL);
   avl = remove_int(avl, 706);
-  avl = gpr_avl_add(avl, box(939), box(416));
+  avl = gpr_avl_add(avl, box(939), box(416), NULL);
   avl = remove_int(avl, 233);
   avl = remove_int(avl, 662);
   avl = remove_int(avl, 984);
   avl = remove_int(avl, 203);
-  avl = gpr_avl_add(avl, box(326), box(421));
+  avl = gpr_avl_add(avl, box(326), box(421), NULL);
   avl = remove_int(avl, 848);
-  avl = gpr_avl_add(avl, box(235), box(423));
+  avl = gpr_avl_add(avl, box(235), box(423), NULL);
   avl = remove_int(avl, 617);
-  avl = gpr_avl_add(avl, box(565), box(425));
+  avl = gpr_avl_add(avl, box(565), box(425), NULL);
   avl = remove_int(avl, 469);
-  avl = gpr_avl_add(avl, box(988), box(427));
+  avl = gpr_avl_add(avl, box(988), box(427), NULL);
   avl = remove_int(avl, 957);
-  avl = gpr_avl_add(avl, box(426), box(429));
+  avl = gpr_avl_add(avl, box(426), box(429), NULL);
   avl = remove_int(avl, 967);
-  avl = gpr_avl_add(avl, box(890), box(431));
-  avl = gpr_avl_add(avl, box(473), box(432));
+  avl = gpr_avl_add(avl, box(890), box(431), NULL);
+  avl = gpr_avl_add(avl, box(473), box(432), NULL);
   avl = remove_int(avl, 367);
   avl = remove_int(avl, 344);
   avl = remove_int(avl, 660);
   avl = remove_int(avl, 448);
   avl = remove_int(avl, 837);
   avl = remove_int(avl, 158);
-  avl = gpr_avl_add(avl, box(459), box(439));
+  avl = gpr_avl_add(avl, box(459), box(439), NULL);
   avl = remove_int(avl, 882);
   avl = remove_int(avl, 782);
-  avl = gpr_avl_add(avl, box(408), box(442));
-  avl = gpr_avl_add(avl, box(728), box(443));
+  avl = gpr_avl_add(avl, box(408), box(442), NULL);
+  avl = gpr_avl_add(avl, box(728), box(443), NULL);
   avl = remove_int(avl, 27);
-  avl = gpr_avl_add(avl, box(137), box(445));
-  avl = gpr_avl_add(avl, box(239), box(446));
+  avl = gpr_avl_add(avl, box(137), box(445), NULL);
+  avl = gpr_avl_add(avl, box(239), box(446), NULL);
   avl = remove_int(avl, 854);
-  avl = gpr_avl_add(avl, box(104), box(448));
-  avl = gpr_avl_add(avl, box(823), box(449));
-  avl = gpr_avl_add(avl, box(524), box(450));
-  avl = gpr_avl_add(avl, box(995), box(451));
+  avl = gpr_avl_add(avl, box(104), box(448), NULL);
+  avl = gpr_avl_add(avl, box(823), box(449), NULL);
+  avl = gpr_avl_add(avl, box(524), box(450), NULL);
+  avl = gpr_avl_add(avl, box(995), box(451), NULL);
   avl = remove_int(avl, 422);
   avl = remove_int(avl, 220);
-  avl = gpr_avl_add(avl, box(856), box(454));
+  avl = gpr_avl_add(avl, box(856), box(454), NULL);
   avl = remove_int(avl, 332);
-  avl = gpr_avl_add(avl, box(679), box(456));
+  avl = gpr_avl_add(avl, box(679), box(456), NULL);
   avl = remove_int(avl, 18);
-  avl = gpr_avl_add(avl, box(837), box(458));
+  avl = gpr_avl_add(avl, box(837), box(458), NULL);
   avl = remove_int(avl, 405);
   avl = remove_int(avl, 877);
   avl = remove_int(avl, 835);
-  avl = gpr_avl_add(avl, box(547), box(462));
+  avl = gpr_avl_add(avl, box(547), box(462), NULL);
   avl = remove_int(avl, 805);
   avl = remove_int(avl, 862);
-  avl = gpr_avl_add(avl, box(75), box(465));
+  avl = gpr_avl_add(avl, box(75), box(465), NULL);
   avl = remove_int(avl, 41);
-  avl = gpr_avl_add(avl, box(310), box(467));
+  avl = gpr_avl_add(avl, box(310), box(467), NULL);
   avl = remove_int(avl, 855);
-  avl = gpr_avl_add(avl, box(20), box(469));
+  avl = gpr_avl_add(avl, box(20), box(469), NULL);
   avl = remove_int(avl, 186);
   avl = remove_int(avl, 378);
   avl = remove_int(avl, 442);
   avl = remove_int(avl, 930);
-  avl = gpr_avl_add(avl, box(118), box(474));
-  avl = gpr_avl_add(avl, box(96), box(475));
+  avl = gpr_avl_add(avl, box(118), box(474), NULL);
+  avl = gpr_avl_add(avl, box(96), box(475), NULL);
   avl = remove_int(avl, 854);
-  avl = gpr_avl_add(avl, box(65), box(477));
-  avl = gpr_avl_add(avl, box(573), box(478));
-  avl = gpr_avl_add(avl, box(4), box(479));
-  avl = gpr_avl_add(avl, box(451), box(480));
-  avl = gpr_avl_add(avl, box(774), box(481));
-  avl = gpr_avl_add(avl, box(126), box(482));
+  avl = gpr_avl_add(avl, box(65), box(477), NULL);
+  avl = gpr_avl_add(avl, box(573), box(478), NULL);
+  avl = gpr_avl_add(avl, box(4), box(479), NULL);
+  avl = gpr_avl_add(avl, box(451), box(480), NULL);
+  avl = gpr_avl_add(avl, box(774), box(481), NULL);
+  avl = gpr_avl_add(avl, box(126), box(482), NULL);
   avl = remove_int(avl, 956);
   avl = remove_int(avl, 591);
   avl = remove_int(avl, 644);
-  avl = gpr_avl_add(avl, box(304), box(486));
+  avl = gpr_avl_add(avl, box(304), box(486), NULL);
   avl = remove_int(avl, 620);
   avl = remove_int(avl, 394);
-  avl = gpr_avl_add(avl, box(1002), box(489));
-  avl = gpr_avl_add(avl, box(837), box(490));
+  avl = gpr_avl_add(avl, box(1002), box(489), NULL);
+  avl = gpr_avl_add(avl, box(837), box(490), NULL);
   avl = remove_int(avl, 485);
-  avl = gpr_avl_add(avl, box(1005), box(492));
+  avl = gpr_avl_add(avl, box(1005), box(492), NULL);
   avl = remove_int(avl, 21);
-  avl = gpr_avl_add(avl, box(396), box(494));
+  avl = gpr_avl_add(avl, box(396), box(494), NULL);
   avl = remove_int(avl, 966);
-  avl = gpr_avl_add(avl, box(105), box(496));
-  avl = gpr_avl_add(avl, box(316), box(497));
+  avl = gpr_avl_add(avl, box(105), box(496), NULL);
+  avl = gpr_avl_add(avl, box(316), box(497), NULL);
   avl = remove_int(avl, 776);
-  avl = gpr_avl_add(avl, box(188), box(499));
+  avl = gpr_avl_add(avl, box(188), box(499), NULL);
   avl = remove_int(avl, 200);
-  avl = gpr_avl_add(avl, box(98), box(501));
-  avl = gpr_avl_add(avl, box(831), box(502));
-  avl = gpr_avl_add(avl, box(227), box(503));
-  avl = gpr_avl_add(avl, box(220), box(504));
+  avl = gpr_avl_add(avl, box(98), box(501), NULL);
+  avl = gpr_avl_add(avl, box(831), box(502), NULL);
+  avl = gpr_avl_add(avl, box(227), box(503), NULL);
+  avl = gpr_avl_add(avl, box(220), box(504), NULL);
   avl = remove_int(avl, 715);
   avl = remove_int(avl, 279);
-  avl = gpr_avl_add(avl, box(701), box(507));
-  avl = gpr_avl_add(avl, box(726), box(508));
-  avl = gpr_avl_add(avl, box(815), box(509));
-  avl = gpr_avl_add(avl, box(749), box(510));
+  avl = gpr_avl_add(avl, box(701), box(507), NULL);
+  avl = gpr_avl_add(avl, box(726), box(508), NULL);
+  avl = gpr_avl_add(avl, box(815), box(509), NULL);
+  avl = gpr_avl_add(avl, box(749), box(510), NULL);
   avl = remove_int(avl, 946);
   avl = remove_int(avl, 449);
   avl = remove_int(avl, 62);
   avl = remove_int(avl, 487);
-  avl = gpr_avl_add(avl, box(545), box(515));
+  avl = gpr_avl_add(avl, box(545), box(515), NULL);
   avl = remove_int(avl, 59);
-  avl = gpr_avl_add(avl, box(168), box(517));
+  avl = gpr_avl_add(avl, box(168), box(517), NULL);
   avl = remove_int(avl, 337);
-  avl = gpr_avl_add(avl, box(69), box(519));
+  avl = gpr_avl_add(avl, box(69), box(519), NULL);
   avl = remove_int(avl, 600);
-  avl = gpr_avl_add(avl, box(591), box(521));
-  avl = gpr_avl_add(avl, box(960), box(522));
-  avl = gpr_avl_add(avl, box(116), box(523));
+  avl = gpr_avl_add(avl, box(591), box(521), NULL);
+  avl = gpr_avl_add(avl, box(960), box(522), NULL);
+  avl = gpr_avl_add(avl, box(116), box(523), NULL);
   avl = remove_int(avl, 991);
-  avl = gpr_avl_add(avl, box(760), box(525));
-  avl = gpr_avl_add(avl, box(664), box(526));
-  avl = gpr_avl_add(avl, box(547), box(527));
+  avl = gpr_avl_add(avl, box(760), box(525), NULL);
+  avl = gpr_avl_add(avl, box(664), box(526), NULL);
+  avl = gpr_avl_add(avl, box(547), box(527), NULL);
   avl = remove_int(avl, 922);
-  avl = gpr_avl_add(avl, box(290), box(529));
-  avl = gpr_avl_add(avl, box(859), box(530));
-  avl = gpr_avl_add(avl, box(49), box(531));
+  avl = gpr_avl_add(avl, box(290), box(529), NULL);
+  avl = gpr_avl_add(avl, box(859), box(530), NULL);
+  avl = gpr_avl_add(avl, box(49), box(531), NULL);
   avl = remove_int(avl, 455);
   avl = remove_int(avl, 786);
-  avl = gpr_avl_add(avl, box(613), box(534));
-  avl = gpr_avl_add(avl, box(326), box(535));
+  avl = gpr_avl_add(avl, box(613), box(534), NULL);
+  avl = gpr_avl_add(avl, box(326), box(535), NULL);
   avl = remove_int(avl, 615);
-  avl = gpr_avl_add(avl, box(45), box(537));
-  avl = gpr_avl_add(avl, box(162), box(538));
-  avl = gpr_avl_add(avl, box(189), box(539));
+  avl = gpr_avl_add(avl, box(45), box(537), NULL);
+  avl = gpr_avl_add(avl, box(162), box(538), NULL);
+  avl = gpr_avl_add(avl, box(189), box(539), NULL);
   avl = remove_int(avl, 68);
   avl = remove_int(avl, 846);
-  avl = gpr_avl_add(avl, box(608), box(542));
+  avl = gpr_avl_add(avl, box(608), box(542), NULL);
   avl = remove_int(avl, 821);
-  avl = gpr_avl_add(avl, box(978), box(544));
-  avl = gpr_avl_add(avl, box(892), box(545));
+  avl = gpr_avl_add(avl, box(978), box(544), NULL);
+  avl = gpr_avl_add(avl, box(892), box(545), NULL);
   avl = remove_int(avl, 924);
-  avl = gpr_avl_add(avl, box(708), box(547));
+  avl = gpr_avl_add(avl, box(708), box(547), NULL);
   avl = remove_int(avl, 135);
   avl = remove_int(avl, 124);
-  avl = gpr_avl_add(avl, box(301), box(550));
-  avl = gpr_avl_add(avl, box(939), box(551));
-  avl = gpr_avl_add(avl, box(344), box(552));
+  avl = gpr_avl_add(avl, box(301), box(550), NULL);
+  avl = gpr_avl_add(avl, box(939), box(551), NULL);
+  avl = gpr_avl_add(avl, box(344), box(552), NULL);
   avl = remove_int(avl, 443);
   avl = remove_int(avl, 122);
-  avl = gpr_avl_add(avl, box(636), box(555));
+  avl = gpr_avl_add(avl, box(636), box(555), NULL);
   avl = remove_int(avl, 558);
-  avl = gpr_avl_add(avl, box(923), box(557));
+  avl = gpr_avl_add(avl, box(923), box(557), NULL);
   avl = remove_int(avl, 827);
-  avl = gpr_avl_add(avl, box(649), box(559));
-  avl = gpr_avl_add(avl, box(808), box(560));
+  avl = gpr_avl_add(avl, box(649), box(559), NULL);
+  avl = gpr_avl_add(avl, box(808), box(560), NULL);
   avl = remove_int(avl, 570);
   avl = remove_int(avl, 434);
-  avl = gpr_avl_add(avl, box(40), box(563));
-  avl = gpr_avl_add(avl, box(725), box(564));
+  avl = gpr_avl_add(avl, box(40), box(563), NULL);
+  avl = gpr_avl_add(avl, box(725), box(564), NULL);
   avl = remove_int(avl, 295);
   avl = remove_int(avl, 615);
   avl = remove_int(avl, 919);
   avl = remove_int(avl, 170);
   avl = remove_int(avl, 442);
   avl = remove_int(avl, 971);
-  avl = gpr_avl_add(avl, box(483), box(571));
-  avl = gpr_avl_add(avl, box(512), box(572));
+  avl = gpr_avl_add(avl, box(483), box(571), NULL);
+  avl = gpr_avl_add(avl, box(512), box(572), NULL);
   avl = remove_int(avl, 648);
   avl = remove_int(avl, 78);
   avl = remove_int(avl, 72);
   avl = remove_int(avl, 790);
   avl = remove_int(avl, 571);
-  avl = gpr_avl_add(avl, box(898), box(578));
+  avl = gpr_avl_add(avl, box(898), box(578), NULL);
   avl = remove_int(avl, 770);
   avl = remove_int(avl, 776);
-  avl = gpr_avl_add(avl, box(602), box(581));
+  avl = gpr_avl_add(avl, box(602), box(581), NULL);
   avl = remove_int(avl, 251);
-  avl = gpr_avl_add(avl, box(303), box(583));
+  avl = gpr_avl_add(avl, box(303), box(583), NULL);
   avl = remove_int(avl, 837);
-  avl = gpr_avl_add(avl, box(714), box(585));
+  avl = gpr_avl_add(avl, box(714), box(585), NULL);
   avl = remove_int(avl, 800);
-  avl = gpr_avl_add(avl, box(266), box(587));
-  avl = gpr_avl_add(avl, box(555), box(588));
+  avl = gpr_avl_add(avl, box(266), box(587), NULL);
+  avl = gpr_avl_add(avl, box(555), box(588), NULL);
   avl = remove_int(avl, 604);
   avl = remove_int(avl, 163);
   avl = remove_int(avl, 497);
-  avl = gpr_avl_add(avl, box(296), box(592));
+  avl = gpr_avl_add(avl, box(296), box(592), NULL);
   avl = remove_int(avl, 129);
-  avl = gpr_avl_add(avl, box(656), box(594));
+  avl = gpr_avl_add(avl, box(656), box(594), NULL);
   avl = remove_int(avl, 769);
   avl = remove_int(avl, 941);
-  avl = gpr_avl_add(avl, box(775), box(597));
-  avl = gpr_avl_add(avl, box(846), box(598));
+  avl = gpr_avl_add(avl, box(775), box(597), NULL);
+  avl = gpr_avl_add(avl, box(846), box(598), NULL);
   avl = remove_int(avl, 591);
   avl = remove_int(avl, 801);
   avl = remove_int(avl, 419);
   avl = remove_int(avl, 455);
-  avl = gpr_avl_add(avl, box(866), box(603));
-  avl = gpr_avl_add(avl, box(575), box(604));
-  avl = gpr_avl_add(avl, box(620), box(605));
+  avl = gpr_avl_add(avl, box(866), box(603), NULL);
+  avl = gpr_avl_add(avl, box(575), box(604), NULL);
+  avl = gpr_avl_add(avl, box(620), box(605), NULL);
   avl = remove_int(avl, 100);
   avl = remove_int(avl, 667);
-  avl = gpr_avl_add(avl, box(138), box(608));
-  avl = gpr_avl_add(avl, box(566), box(609));
-  avl = gpr_avl_add(avl, box(673), box(610));
-  avl = gpr_avl_add(avl, box(178), box(611));
+  avl = gpr_avl_add(avl, box(138), box(608), NULL);
+  avl = gpr_avl_add(avl, box(566), box(609), NULL);
+  avl = gpr_avl_add(avl, box(673), box(610), NULL);
+  avl = gpr_avl_add(avl, box(178), box(611), NULL);
   avl = remove_int(avl, 659);
-  avl = gpr_avl_add(avl, box(759), box(613));
-  avl = gpr_avl_add(avl, box(1008), box(614));
+  avl = gpr_avl_add(avl, box(759), box(613), NULL);
+  avl = gpr_avl_add(avl, box(1008), box(614), NULL);
   avl = remove_int(avl, 116);
-  avl = gpr_avl_add(avl, box(608), box(616));
-  avl = gpr_avl_add(avl, box(339), box(617));
-  avl = gpr_avl_add(avl, box(197), box(618));
+  avl = gpr_avl_add(avl, box(608), box(616), NULL);
+  avl = gpr_avl_add(avl, box(339), box(617), NULL);
+  avl = gpr_avl_add(avl, box(197), box(618), NULL);
   avl = remove_int(avl, 25);
   avl = remove_int(avl, 628);
-  avl = gpr_avl_add(avl, box(487), box(621));
+  avl = gpr_avl_add(avl, box(487), box(621), NULL);
   avl = remove_int(avl, 739);
   avl = remove_int(avl, 100);
   avl = remove_int(avl, 928);
-  avl = gpr_avl_add(avl, box(647), box(625));
+  avl = gpr_avl_add(avl, box(647), box(625), NULL);
   avl = remove_int(avl, 978);
   avl = remove_int(avl, 143);
   avl = remove_int(avl, 755);
-  avl = gpr_avl_add(avl, box(71), box(629));
+  avl = gpr_avl_add(avl, box(71), box(629), NULL);
   avl = remove_int(avl, 205);
-  avl = gpr_avl_add(avl, box(501), box(631));
+  avl = gpr_avl_add(avl, box(501), box(631), NULL);
   avl = remove_int(avl, 723);
   avl = remove_int(avl, 852);
   avl = remove_int(avl, 1021);
   avl = remove_int(avl, 670);
   avl = remove_int(avl, 500);
-  avl = gpr_avl_add(avl, box(330), box(637));
+  avl = gpr_avl_add(avl, box(330), box(637), NULL);
   avl = remove_int(avl, 264);
-  avl = gpr_avl_add(avl, box(69), box(639));
+  avl = gpr_avl_add(avl, box(69), box(639), NULL);
   avl = remove_int(avl, 73);
-  avl = gpr_avl_add(avl, box(745), box(641));
+  avl = gpr_avl_add(avl, box(745), box(641), NULL);
   avl = remove_int(avl, 518);
   avl = remove_int(avl, 641);
   avl = remove_int(avl, 768);
-  avl = gpr_avl_add(avl, box(988), box(645));
-  avl = gpr_avl_add(avl, box(899), box(646));
+  avl = gpr_avl_add(avl, box(988), box(645), NULL);
+  avl = gpr_avl_add(avl, box(899), box(646), NULL);
   avl = remove_int(avl, 763);
   avl = remove_int(avl, 281);
   avl = remove_int(avl, 496);
-  avl = gpr_avl_add(avl, box(445), box(650));
+  avl = gpr_avl_add(avl, box(445), box(650), NULL);
   avl = remove_int(avl, 905);
-  avl = gpr_avl_add(avl, box(275), box(652));
-  avl = gpr_avl_add(avl, box(137), box(653));
+  avl = gpr_avl_add(avl, box(275), box(652), NULL);
+  avl = gpr_avl_add(avl, box(137), box(653), NULL);
   avl = remove_int(avl, 642);
-  avl = gpr_avl_add(avl, box(708), box(655));
+  avl = gpr_avl_add(avl, box(708), box(655), NULL);
   avl = remove_int(avl, 922);
-  avl = gpr_avl_add(avl, box(743), box(657));
+  avl = gpr_avl_add(avl, box(743), box(657), NULL);
   avl = remove_int(avl, 295);
   avl = remove_int(avl, 665);
   avl = remove_int(avl, 48);
-  avl = gpr_avl_add(avl, box(1012), box(661));
+  avl = gpr_avl_add(avl, box(1012), box(661), NULL);
   avl = remove_int(avl, 71);
   avl = remove_int(avl, 523);
-  avl = gpr_avl_add(avl, box(319), box(664));
+  avl = gpr_avl_add(avl, box(319), box(664), NULL);
   avl = remove_int(avl, 632);
-  avl = gpr_avl_add(avl, box(137), box(666));
-  avl = gpr_avl_add(avl, box(686), box(667));
-  avl = gpr_avl_add(avl, box(724), box(668));
-  avl = gpr_avl_add(avl, box(952), box(669));
-  avl = gpr_avl_add(avl, box(5), box(670));
+  avl = gpr_avl_add(avl, box(137), box(666), NULL);
+  avl = gpr_avl_add(avl, box(686), box(667), NULL);
+  avl = gpr_avl_add(avl, box(724), box(668), NULL);
+  avl = gpr_avl_add(avl, box(952), box(669), NULL);
+  avl = gpr_avl_add(avl, box(5), box(670), NULL);
   avl = remove_int(avl, 35);
-  avl = gpr_avl_add(avl, box(43), box(672));
-  avl = gpr_avl_add(avl, box(320), box(673));
-  avl = gpr_avl_add(avl, box(115), box(674));
+  avl = gpr_avl_add(avl, box(43), box(672), NULL);
+  avl = gpr_avl_add(avl, box(320), box(673), NULL);
+  avl = gpr_avl_add(avl, box(115), box(674), NULL);
   avl = remove_int(avl, 377);
   avl = remove_int(avl, 591);
   avl = remove_int(avl, 87);
   avl = remove_int(avl, 93);
-  avl = gpr_avl_add(avl, box(1016), box(679));
-  avl = gpr_avl_add(avl, box(605), box(680));
-  avl = gpr_avl_add(avl, box(152), box(681));
-  avl = gpr_avl_add(avl, box(113), box(682));
+  avl = gpr_avl_add(avl, box(1016), box(679), NULL);
+  avl = gpr_avl_add(avl, box(605), box(680), NULL);
+  avl = gpr_avl_add(avl, box(152), box(681), NULL);
+  avl = gpr_avl_add(avl, box(113), box(682), NULL);
   avl = remove_int(avl, 131);
   avl = remove_int(avl, 637);
-  avl = gpr_avl_add(avl, box(156), box(685));
+  avl = gpr_avl_add(avl, box(156), box(685), NULL);
   avl = remove_int(avl, 696);
-  avl = gpr_avl_add(avl, box(546), box(687));
+  avl = gpr_avl_add(avl, box(546), box(687), NULL);
   avl = remove_int(avl, 970);
   avl = remove_int(avl, 53);
   avl = remove_int(avl, 827);
@@ -1837,22 +1839,22 @@
   avl = remove_int(avl, 244);
   avl = remove_int(avl, 576);
   avl = remove_int(avl, 413);
-  avl = gpr_avl_add(avl, box(500), box(701));
+  avl = gpr_avl_add(avl, box(500), box(701), NULL);
   avl = remove_int(avl, 924);
-  avl = gpr_avl_add(avl, box(825), box(703));
+  avl = gpr_avl_add(avl, box(825), box(703), NULL);
   avl = remove_int(avl, 888);
   avl = remove_int(avl, 931);
-  avl = gpr_avl_add(avl, box(285), box(706));
+  avl = gpr_avl_add(avl, box(285), box(706), NULL);
   avl = remove_int(avl, 62);
   avl = remove_int(avl, 444);
   avl = remove_int(avl, 946);
-  avl = gpr_avl_add(avl, box(122), box(710));
-  avl = gpr_avl_add(avl, box(846), box(711));
+  avl = gpr_avl_add(avl, box(122), box(710), NULL);
+  avl = gpr_avl_add(avl, box(846), box(711), NULL);
   avl = remove_int(avl, 628);
-  avl = gpr_avl_add(avl, box(511), box(713));
-  avl = gpr_avl_add(avl, box(398), box(714));
+  avl = gpr_avl_add(avl, box(511), box(713), NULL);
+  avl = gpr_avl_add(avl, box(398), box(714), NULL);
   avl = remove_int(avl, 730);
-  avl = gpr_avl_add(avl, box(797), box(716));
+  avl = gpr_avl_add(avl, box(797), box(716), NULL);
   avl = remove_int(avl, 897);
   avl = remove_int(avl, 228);
   avl = remove_int(avl, 544);
@@ -1861,51 +1863,51 @@
   avl = remove_int(avl, 583);
   avl = remove_int(avl, 894);
   avl = remove_int(avl, 942);
-  avl = gpr_avl_add(avl, box(346), box(725));
-  avl = gpr_avl_add(avl, box(1015), box(726));
+  avl = gpr_avl_add(avl, box(346), box(725), NULL);
+  avl = gpr_avl_add(avl, box(1015), box(726), NULL);
   avl = remove_int(avl, 813);
-  avl = gpr_avl_add(avl, box(213), box(728));
+  avl = gpr_avl_add(avl, box(213), box(728), NULL);
   avl = remove_int(avl, 468);
   avl = remove_int(avl, 365);
   avl = remove_int(avl, 399);
-  avl = gpr_avl_add(avl, box(380), box(732));
+  avl = gpr_avl_add(avl, box(380), box(732), NULL);
   avl = remove_int(avl, 835);
   avl = remove_int(avl, 970);
-  avl = gpr_avl_add(avl, box(700), box(735));
-  avl = gpr_avl_add(avl, box(807), box(736));
+  avl = gpr_avl_add(avl, box(700), box(735), NULL);
+  avl = gpr_avl_add(avl, box(807), box(736), NULL);
   avl = remove_int(avl, 312);
   avl = remove_int(avl, 282);
   avl = remove_int(avl, 370);
   avl = remove_int(avl, 999);
   avl = remove_int(avl, 241);
   avl = remove_int(avl, 884);
-  avl = gpr_avl_add(avl, box(587), box(743));
-  avl = gpr_avl_add(avl, box(332), box(744));
+  avl = gpr_avl_add(avl, box(587), box(743), NULL);
+  avl = gpr_avl_add(avl, box(332), box(744), NULL);
   avl = remove_int(avl, 686);
   avl = remove_int(avl, 206);
   avl = remove_int(avl, 835);
-  avl = gpr_avl_add(avl, box(334), box(748));
+  avl = gpr_avl_add(avl, box(334), box(748), NULL);
   avl = remove_int(avl, 171);
-  avl = gpr_avl_add(avl, box(1002), box(750));
-  avl = gpr_avl_add(avl, box(779), box(751));
-  avl = gpr_avl_add(avl, box(307), box(752));
-  avl = gpr_avl_add(avl, box(127), box(753));
-  avl = gpr_avl_add(avl, box(251), box(754));
+  avl = gpr_avl_add(avl, box(1002), box(750), NULL);
+  avl = gpr_avl_add(avl, box(779), box(751), NULL);
+  avl = gpr_avl_add(avl, box(307), box(752), NULL);
+  avl = gpr_avl_add(avl, box(127), box(753), NULL);
+  avl = gpr_avl_add(avl, box(251), box(754), NULL);
   avl = remove_int(avl, 790);
   avl = remove_int(avl, 189);
   avl = remove_int(avl, 193);
   avl = remove_int(avl, 38);
   avl = remove_int(avl, 124);
-  avl = gpr_avl_add(avl, box(812), box(760));
+  avl = gpr_avl_add(avl, box(812), box(760), NULL);
   avl = remove_int(avl, 43);
-  avl = gpr_avl_add(avl, box(871), box(762));
-  avl = gpr_avl_add(avl, box(580), box(763));
+  avl = gpr_avl_add(avl, box(871), box(762), NULL);
+  avl = gpr_avl_add(avl, box(580), box(763), NULL);
   avl = remove_int(avl, 501);
   avl = remove_int(avl, 462);
   avl = remove_int(avl, 599);
-  avl = gpr_avl_add(avl, box(240), box(767));
-  avl = gpr_avl_add(avl, box(285), box(768));
-  avl = gpr_avl_add(avl, box(472), box(769));
+  avl = gpr_avl_add(avl, box(240), box(767), NULL);
+  avl = gpr_avl_add(avl, box(285), box(768), NULL);
+  avl = gpr_avl_add(avl, box(472), box(769), NULL);
   avl = remove_int(avl, 865);
   avl = remove_int(avl, 763);
   avl = remove_int(avl, 245);
@@ -1913,48 +1915,48 @@
   avl = remove_int(avl, 713);
   avl = remove_int(avl, 654);
   avl = remove_int(avl, 1014);
-  avl = gpr_avl_add(avl, box(495), box(777));
-  avl = gpr_avl_add(avl, box(552), box(778));
+  avl = gpr_avl_add(avl, box(495), box(777), NULL);
+  avl = gpr_avl_add(avl, box(552), box(778), NULL);
   avl = remove_int(avl, 19);
   avl = remove_int(avl, 803);
-  avl = gpr_avl_add(avl, box(508), box(781));
+  avl = gpr_avl_add(avl, box(508), box(781), NULL);
   avl = remove_int(avl, 699);
   avl = remove_int(avl, 260);
   avl = remove_int(avl, 92);
   avl = remove_int(avl, 497);
-  avl = gpr_avl_add(avl, box(970), box(786));
+  avl = gpr_avl_add(avl, box(970), box(786), NULL);
   avl = remove_int(avl, 987);
   avl = remove_int(avl, 168);
   avl = remove_int(avl, 476);
   avl = remove_int(avl, 248);
-  avl = gpr_avl_add(avl, box(358), box(791));
+  avl = gpr_avl_add(avl, box(358), box(791), NULL);
   avl = remove_int(avl, 804);
   avl = remove_int(avl, 77);
   avl = remove_int(avl, 905);
   avl = remove_int(avl, 362);
-  avl = gpr_avl_add(avl, box(578), box(796));
+  avl = gpr_avl_add(avl, box(578), box(796), NULL);
   avl = remove_int(avl, 38);
   avl = remove_int(avl, 595);
-  avl = gpr_avl_add(avl, box(213), box(799));
+  avl = gpr_avl_add(avl, box(213), box(799), NULL);
   avl = remove_int(avl, 7);
   avl = remove_int(avl, 620);
-  avl = gpr_avl_add(avl, box(946), box(802));
+  avl = gpr_avl_add(avl, box(946), box(802), NULL);
   avl = remove_int(avl, 145);
-  avl = gpr_avl_add(avl, box(628), box(804));
+  avl = gpr_avl_add(avl, box(628), box(804), NULL);
   avl = remove_int(avl, 972);
-  avl = gpr_avl_add(avl, box(728), box(806));
+  avl = gpr_avl_add(avl, box(728), box(806), NULL);
   avl = remove_int(avl, 91);
-  avl = gpr_avl_add(avl, box(136), box(808));
-  avl = gpr_avl_add(avl, box(841), box(809));
-  avl = gpr_avl_add(avl, box(265), box(810));
-  avl = gpr_avl_add(avl, box(701), box(811));
-  avl = gpr_avl_add(avl, box(27), box(812));
+  avl = gpr_avl_add(avl, box(136), box(808), NULL);
+  avl = gpr_avl_add(avl, box(841), box(809), NULL);
+  avl = gpr_avl_add(avl, box(265), box(810), NULL);
+  avl = gpr_avl_add(avl, box(701), box(811), NULL);
+  avl = gpr_avl_add(avl, box(27), box(812), NULL);
   avl = remove_int(avl, 72);
   avl = remove_int(avl, 14);
-  avl = gpr_avl_add(avl, box(286), box(815));
+  avl = gpr_avl_add(avl, box(286), box(815), NULL);
   avl = remove_int(avl, 996);
   avl = remove_int(avl, 998);
-  avl = gpr_avl_add(avl, box(466), box(818));
+  avl = gpr_avl_add(avl, box(466), box(818), NULL);
   avl = remove_int(avl, 1009);
   avl = remove_int(avl, 741);
   avl = remove_int(avl, 947);
@@ -1963,138 +1965,138 @@
   avl = remove_int(avl, 183);
   avl = remove_int(avl, 395);
   avl = remove_int(avl, 951);
-  avl = gpr_avl_add(avl, box(267), box(827));
+  avl = gpr_avl_add(avl, box(267), box(827), NULL);
   avl = remove_int(avl, 812);
-  avl = gpr_avl_add(avl, box(577), box(829));
+  avl = gpr_avl_add(avl, box(577), box(829), NULL);
   avl = remove_int(avl, 624);
   avl = remove_int(avl, 847);
   avl = remove_int(avl, 745);
-  avl = gpr_avl_add(avl, box(491), box(833));
-  avl = gpr_avl_add(avl, box(941), box(834));
+  avl = gpr_avl_add(avl, box(491), box(833), NULL);
+  avl = gpr_avl_add(avl, box(941), box(834), NULL);
   avl = remove_int(avl, 258);
-  avl = gpr_avl_add(avl, box(410), box(836));
-  avl = gpr_avl_add(avl, box(80), box(837));
-  avl = gpr_avl_add(avl, box(196), box(838));
-  avl = gpr_avl_add(avl, box(5), box(839));
+  avl = gpr_avl_add(avl, box(410), box(836), NULL);
+  avl = gpr_avl_add(avl, box(80), box(837), NULL);
+  avl = gpr_avl_add(avl, box(196), box(838), NULL);
+  avl = gpr_avl_add(avl, box(5), box(839), NULL);
   avl = remove_int(avl, 782);
-  avl = gpr_avl_add(avl, box(827), box(841));
+  avl = gpr_avl_add(avl, box(827), box(841), NULL);
   avl = remove_int(avl, 472);
   avl = remove_int(avl, 664);
-  avl = gpr_avl_add(avl, box(409), box(844));
-  avl = gpr_avl_add(avl, box(62), box(845));
+  avl = gpr_avl_add(avl, box(409), box(844), NULL);
+  avl = gpr_avl_add(avl, box(62), box(845), NULL);
   avl = remove_int(avl, 56);
   avl = remove_int(avl, 606);
   avl = remove_int(avl, 707);
   avl = remove_int(avl, 989);
   avl = remove_int(avl, 549);
   avl = remove_int(avl, 259);
-  avl = gpr_avl_add(avl, box(405), box(852));
+  avl = gpr_avl_add(avl, box(405), box(852), NULL);
   avl = remove_int(avl, 587);
   avl = remove_int(avl, 350);
-  avl = gpr_avl_add(avl, box(980), box(855));
-  avl = gpr_avl_add(avl, box(992), box(856));
-  avl = gpr_avl_add(avl, box(818), box(857));
+  avl = gpr_avl_add(avl, box(980), box(855), NULL);
+  avl = gpr_avl_add(avl, box(992), box(856), NULL);
+  avl = gpr_avl_add(avl, box(818), box(857), NULL);
   avl = remove_int(avl, 853);
   avl = remove_int(avl, 701);
-  avl = gpr_avl_add(avl, box(675), box(860));
+  avl = gpr_avl_add(avl, box(675), box(860), NULL);
   avl = remove_int(avl, 248);
   avl = remove_int(avl, 649);
-  avl = gpr_avl_add(avl, box(508), box(863));
+  avl = gpr_avl_add(avl, box(508), box(863), NULL);
   avl = remove_int(avl, 927);
-  avl = gpr_avl_add(avl, box(957), box(865));
-  avl = gpr_avl_add(avl, box(698), box(866));
-  avl = gpr_avl_add(avl, box(388), box(867));
-  avl = gpr_avl_add(avl, box(532), box(868));
-  avl = gpr_avl_add(avl, box(681), box(869));
+  avl = gpr_avl_add(avl, box(957), box(865), NULL);
+  avl = gpr_avl_add(avl, box(698), box(866), NULL);
+  avl = gpr_avl_add(avl, box(388), box(867), NULL);
+  avl = gpr_avl_add(avl, box(532), box(868), NULL);
+  avl = gpr_avl_add(avl, box(681), box(869), NULL);
   avl = remove_int(avl, 544);
   avl = remove_int(avl, 991);
   avl = remove_int(avl, 397);
-  avl = gpr_avl_add(avl, box(954), box(873));
-  avl = gpr_avl_add(avl, box(219), box(874));
-  avl = gpr_avl_add(avl, box(465), box(875));
+  avl = gpr_avl_add(avl, box(954), box(873), NULL);
+  avl = gpr_avl_add(avl, box(219), box(874), NULL);
+  avl = gpr_avl_add(avl, box(465), box(875), NULL);
   avl = remove_int(avl, 371);
-  avl = gpr_avl_add(avl, box(601), box(877));
-  avl = gpr_avl_add(avl, box(543), box(878));
+  avl = gpr_avl_add(avl, box(601), box(877), NULL);
+  avl = gpr_avl_add(avl, box(543), box(878), NULL);
   avl = remove_int(avl, 329);
-  avl = gpr_avl_add(avl, box(560), box(880));
+  avl = gpr_avl_add(avl, box(560), box(880), NULL);
   avl = remove_int(avl, 898);
-  avl = gpr_avl_add(avl, box(455), box(882));
+  avl = gpr_avl_add(avl, box(455), box(882), NULL);
   avl = remove_int(avl, 313);
-  avl = gpr_avl_add(avl, box(215), box(884));
+  avl = gpr_avl_add(avl, box(215), box(884), NULL);
   avl = remove_int(avl, 846);
-  avl = gpr_avl_add(avl, box(608), box(886));
+  avl = gpr_avl_add(avl, box(608), box(886), NULL);
   avl = remove_int(avl, 248);
-  avl = gpr_avl_add(avl, box(575), box(888));
+  avl = gpr_avl_add(avl, box(575), box(888), NULL);
   avl = remove_int(avl, 207);
   avl = remove_int(avl, 810);
   avl = remove_int(avl, 665);
   avl = remove_int(avl, 361);
-  avl = gpr_avl_add(avl, box(154), box(893));
-  avl = gpr_avl_add(avl, box(329), box(894));
-  avl = gpr_avl_add(avl, box(326), box(895));
+  avl = gpr_avl_add(avl, box(154), box(893), NULL);
+  avl = gpr_avl_add(avl, box(329), box(894), NULL);
+  avl = gpr_avl_add(avl, box(326), box(895), NULL);
   avl = remove_int(avl, 746);
   avl = remove_int(avl, 99);
-  avl = gpr_avl_add(avl, box(464), box(898));
-  avl = gpr_avl_add(avl, box(141), box(899));
+  avl = gpr_avl_add(avl, box(464), box(898), NULL);
+  avl = gpr_avl_add(avl, box(141), box(899), NULL);
   avl = remove_int(avl, 383);
-  avl = gpr_avl_add(avl, box(414), box(901));
-  avl = gpr_avl_add(avl, box(777), box(902));
+  avl = gpr_avl_add(avl, box(414), box(901), NULL);
+  avl = gpr_avl_add(avl, box(777), box(902), NULL);
   avl = remove_int(avl, 972);
   avl = remove_int(avl, 841);
   avl = remove_int(avl, 100);
-  avl = gpr_avl_add(avl, box(828), box(906));
+  avl = gpr_avl_add(avl, box(828), box(906), NULL);
   avl = remove_int(avl, 785);
-  avl = gpr_avl_add(avl, box(1008), box(908));
-  avl = gpr_avl_add(avl, box(46), box(909));
+  avl = gpr_avl_add(avl, box(1008), box(908), NULL);
+  avl = gpr_avl_add(avl, box(46), box(909), NULL);
   avl = remove_int(avl, 399);
-  avl = gpr_avl_add(avl, box(178), box(911));
-  avl = gpr_avl_add(avl, box(573), box(912));
+  avl = gpr_avl_add(avl, box(178), box(911), NULL);
+  avl = gpr_avl_add(avl, box(573), box(912), NULL);
   avl = remove_int(avl, 299);
-  avl = gpr_avl_add(avl, box(690), box(914));
-  avl = gpr_avl_add(avl, box(692), box(915));
+  avl = gpr_avl_add(avl, box(690), box(914), NULL);
+  avl = gpr_avl_add(avl, box(692), box(915), NULL);
   avl = remove_int(avl, 404);
   avl = remove_int(avl, 16);
   avl = remove_int(avl, 746);
   avl = remove_int(avl, 486);
   avl = remove_int(avl, 119);
-  avl = gpr_avl_add(avl, box(167), box(921));
+  avl = gpr_avl_add(avl, box(167), box(921), NULL);
   avl = remove_int(avl, 328);
-  avl = gpr_avl_add(avl, box(89), box(923));
+  avl = gpr_avl_add(avl, box(89), box(923), NULL);
   avl = remove_int(avl, 867);
   avl = remove_int(avl, 626);
   avl = remove_int(avl, 507);
-  avl = gpr_avl_add(avl, box(365), box(927));
-  avl = gpr_avl_add(avl, box(58), box(928));
-  avl = gpr_avl_add(avl, box(70), box(929));
+  avl = gpr_avl_add(avl, box(365), box(927), NULL);
+  avl = gpr_avl_add(avl, box(58), box(928), NULL);
+  avl = gpr_avl_add(avl, box(70), box(929), NULL);
   avl = remove_int(avl, 81);
   avl = remove_int(avl, 797);
-  avl = gpr_avl_add(avl, box(846), box(932));
+  avl = gpr_avl_add(avl, box(846), box(932), NULL);
   avl = remove_int(avl, 642);
-  avl = gpr_avl_add(avl, box(777), box(934));
+  avl = gpr_avl_add(avl, box(777), box(934), NULL);
   avl = remove_int(avl, 107);
-  avl = gpr_avl_add(avl, box(691), box(936));
-  avl = gpr_avl_add(avl, box(820), box(937));
-  avl = gpr_avl_add(avl, box(202), box(938));
-  avl = gpr_avl_add(avl, box(308), box(939));
-  avl = gpr_avl_add(avl, box(20), box(940));
+  avl = gpr_avl_add(avl, box(691), box(936), NULL);
+  avl = gpr_avl_add(avl, box(820), box(937), NULL);
+  avl = gpr_avl_add(avl, box(202), box(938), NULL);
+  avl = gpr_avl_add(avl, box(308), box(939), NULL);
+  avl = gpr_avl_add(avl, box(20), box(940), NULL);
   avl = remove_int(avl, 289);
-  avl = gpr_avl_add(avl, box(714), box(942));
-  avl = gpr_avl_add(avl, box(584), box(943));
+  avl = gpr_avl_add(avl, box(714), box(942), NULL);
+  avl = gpr_avl_add(avl, box(584), box(943), NULL);
   avl = remove_int(avl, 294);
-  avl = gpr_avl_add(avl, box(496), box(945));
-  avl = gpr_avl_add(avl, box(394), box(946));
-  avl = gpr_avl_add(avl, box(860), box(947));
-  avl = gpr_avl_add(avl, box(58), box(948));
+  avl = gpr_avl_add(avl, box(496), box(945), NULL);
+  avl = gpr_avl_add(avl, box(394), box(946), NULL);
+  avl = gpr_avl_add(avl, box(860), box(947), NULL);
+  avl = gpr_avl_add(avl, box(58), box(948), NULL);
   avl = remove_int(avl, 784);
   avl = remove_int(avl, 584);
   avl = remove_int(avl, 708);
-  avl = gpr_avl_add(avl, box(142), box(952));
-  avl = gpr_avl_add(avl, box(247), box(953));
-  avl = gpr_avl_add(avl, box(389), box(954));
+  avl = gpr_avl_add(avl, box(142), box(952), NULL);
+  avl = gpr_avl_add(avl, box(247), box(953), NULL);
+  avl = gpr_avl_add(avl, box(389), box(954), NULL);
   avl = remove_int(avl, 390);
-  avl = gpr_avl_add(avl, box(465), box(956));
-  avl = gpr_avl_add(avl, box(936), box(957));
-  avl = gpr_avl_add(avl, box(309), box(958));
+  avl = gpr_avl_add(avl, box(465), box(956), NULL);
+  avl = gpr_avl_add(avl, box(936), box(957), NULL);
+  avl = gpr_avl_add(avl, box(309), box(958), NULL);
   avl = remove_int(avl, 928);
   avl = remove_int(avl, 128);
   avl = remove_int(avl, 979);
@@ -2102,15 +2104,15 @@
   avl = remove_int(avl, 738);
   avl = remove_int(avl, 271);
   avl = remove_int(avl, 540);
-  avl = gpr_avl_add(avl, box(365), box(966));
+  avl = gpr_avl_add(avl, box(365), box(966), NULL);
   avl = remove_int(avl, 82);
-  avl = gpr_avl_add(avl, box(728), box(968));
+  avl = gpr_avl_add(avl, box(728), box(968), NULL);
   avl = remove_int(avl, 852);
-  avl = gpr_avl_add(avl, box(884), box(970));
-  avl = gpr_avl_add(avl, box(502), box(971));
+  avl = gpr_avl_add(avl, box(884), box(970), NULL);
+  avl = gpr_avl_add(avl, box(502), box(971), NULL);
   avl = remove_int(avl, 898);
   avl = remove_int(avl, 481);
-  avl = gpr_avl_add(avl, box(911), box(974));
+  avl = gpr_avl_add(avl, box(911), box(974), NULL);
   avl = remove_int(avl, 787);
   avl = remove_int(avl, 785);
   avl = remove_int(avl, 537);
@@ -2119,125 +2121,125 @@
   avl = remove_int(avl, 749);
   avl = remove_int(avl, 637);
   avl = remove_int(avl, 900);
-  avl = gpr_avl_add(avl, box(598), box(983));
+  avl = gpr_avl_add(avl, box(598), box(983), NULL);
   avl = remove_int(avl, 25);
   avl = remove_int(avl, 697);
-  avl = gpr_avl_add(avl, box(645), box(986));
-  avl = gpr_avl_add(avl, box(211), box(987));
-  avl = gpr_avl_add(avl, box(589), box(988));
+  avl = gpr_avl_add(avl, box(645), box(986), NULL);
+  avl = gpr_avl_add(avl, box(211), box(987), NULL);
+  avl = gpr_avl_add(avl, box(589), box(988), NULL);
   avl = remove_int(avl, 702);
-  avl = gpr_avl_add(avl, box(53), box(990));
+  avl = gpr_avl_add(avl, box(53), box(990), NULL);
   avl = remove_int(avl, 492);
   avl = remove_int(avl, 185);
   avl = remove_int(avl, 246);
   avl = remove_int(avl, 257);
   avl = remove_int(avl, 502);
   avl = remove_int(avl, 34);
-  avl = gpr_avl_add(avl, box(74), box(997));
-  avl = gpr_avl_add(avl, box(834), box(998));
-  avl = gpr_avl_add(avl, box(514), box(999));
-  avl = gpr_avl_add(avl, box(75), box(1000));
+  avl = gpr_avl_add(avl, box(74), box(997), NULL);
+  avl = gpr_avl_add(avl, box(834), box(998), NULL);
+  avl = gpr_avl_add(avl, box(514), box(999), NULL);
+  avl = gpr_avl_add(avl, box(75), box(1000), NULL);
   avl = remove_int(avl, 745);
-  avl = gpr_avl_add(avl, box(362), box(1002));
+  avl = gpr_avl_add(avl, box(362), box(1002), NULL);
   avl = remove_int(avl, 215);
-  avl = gpr_avl_add(avl, box(624), box(1004));
+  avl = gpr_avl_add(avl, box(624), box(1004), NULL);
   avl = remove_int(avl, 404);
   avl = remove_int(avl, 359);
   avl = remove_int(avl, 491);
-  avl = gpr_avl_add(avl, box(903), box(1008));
-  avl = gpr_avl_add(avl, box(240), box(1009));
+  avl = gpr_avl_add(avl, box(903), box(1008), NULL);
+  avl = gpr_avl_add(avl, box(240), box(1009), NULL);
   avl = remove_int(avl, 95);
-  avl = gpr_avl_add(avl, box(119), box(1011));
-  avl = gpr_avl_add(avl, box(857), box(1012));
+  avl = gpr_avl_add(avl, box(119), box(1011), NULL);
+  avl = gpr_avl_add(avl, box(857), box(1012), NULL);
   avl = remove_int(avl, 39);
   avl = remove_int(avl, 866);
-  avl = gpr_avl_add(avl, box(503), box(1015));
-  avl = gpr_avl_add(avl, box(740), box(1016));
+  avl = gpr_avl_add(avl, box(503), box(1015), NULL);
+  avl = gpr_avl_add(avl, box(740), box(1016), NULL);
   avl = remove_int(avl, 637);
   avl = remove_int(avl, 156);
   avl = remove_int(avl, 6);
   avl = remove_int(avl, 745);
   avl = remove_int(avl, 433);
   avl = remove_int(avl, 283);
-  avl = gpr_avl_add(avl, box(625), box(1023));
+  avl = gpr_avl_add(avl, box(625), box(1023), NULL);
   avl = remove_int(avl, 638);
-  avl = gpr_avl_add(avl, box(299), box(1025));
-  avl = gpr_avl_add(avl, box(584), box(1026));
+  avl = gpr_avl_add(avl, box(299), box(1025), NULL);
+  avl = gpr_avl_add(avl, box(584), box(1026), NULL);
   avl = remove_int(avl, 863);
-  avl = gpr_avl_add(avl, box(612), box(1028));
-  avl = gpr_avl_add(avl, box(62), box(1029));
-  avl = gpr_avl_add(avl, box(432), box(1030));
+  avl = gpr_avl_add(avl, box(612), box(1028), NULL);
+  avl = gpr_avl_add(avl, box(62), box(1029), NULL);
+  avl = gpr_avl_add(avl, box(432), box(1030), NULL);
   avl = remove_int(avl, 371);
   avl = remove_int(avl, 790);
   avl = remove_int(avl, 227);
   avl = remove_int(avl, 836);
-  avl = gpr_avl_add(avl, box(703), box(1035));
-  avl = gpr_avl_add(avl, box(644), box(1036));
+  avl = gpr_avl_add(avl, box(703), box(1035), NULL);
+  avl = gpr_avl_add(avl, box(644), box(1036), NULL);
   avl = remove_int(avl, 638);
-  avl = gpr_avl_add(avl, box(13), box(1038));
+  avl = gpr_avl_add(avl, box(13), box(1038), NULL);
   avl = remove_int(avl, 66);
   avl = remove_int(avl, 82);
-  avl = gpr_avl_add(avl, box(362), box(1041));
-  avl = gpr_avl_add(avl, box(783), box(1042));
+  avl = gpr_avl_add(avl, box(362), box(1041), NULL);
+  avl = gpr_avl_add(avl, box(783), box(1042), NULL);
   avl = remove_int(avl, 60);
-  avl = gpr_avl_add(avl, box(80), box(1044));
-  avl = gpr_avl_add(avl, box(825), box(1045));
-  avl = gpr_avl_add(avl, box(688), box(1046));
-  avl = gpr_avl_add(avl, box(662), box(1047));
+  avl = gpr_avl_add(avl, box(80), box(1044), NULL);
+  avl = gpr_avl_add(avl, box(825), box(1045), NULL);
+  avl = gpr_avl_add(avl, box(688), box(1046), NULL);
+  avl = gpr_avl_add(avl, box(662), box(1047), NULL);
   avl = remove_int(avl, 156);
   avl = remove_int(avl, 376);
   avl = remove_int(avl, 99);
-  avl = gpr_avl_add(avl, box(526), box(1051));
-  avl = gpr_avl_add(avl, box(168), box(1052));
+  avl = gpr_avl_add(avl, box(526), box(1051), NULL);
+  avl = gpr_avl_add(avl, box(168), box(1052), NULL);
   avl = remove_int(avl, 646);
   avl = remove_int(avl, 380);
   avl = remove_int(avl, 833);
-  avl = gpr_avl_add(avl, box(53), box(1056));
+  avl = gpr_avl_add(avl, box(53), box(1056), NULL);
   avl = remove_int(avl, 105);
-  avl = gpr_avl_add(avl, box(373), box(1058));
-  avl = gpr_avl_add(avl, box(184), box(1059));
+  avl = gpr_avl_add(avl, box(373), box(1058), NULL);
+  avl = gpr_avl_add(avl, box(184), box(1059), NULL);
   avl = remove_int(avl, 288);
-  avl = gpr_avl_add(avl, box(966), box(1061));
+  avl = gpr_avl_add(avl, box(966), box(1061), NULL);
   avl = remove_int(avl, 158);
-  avl = gpr_avl_add(avl, box(406), box(1063));
+  avl = gpr_avl_add(avl, box(406), box(1063), NULL);
   avl = remove_int(avl, 470);
-  avl = gpr_avl_add(avl, box(283), box(1065));
-  avl = gpr_avl_add(avl, box(838), box(1066));
-  avl = gpr_avl_add(avl, box(288), box(1067));
-  avl = gpr_avl_add(avl, box(950), box(1068));
-  avl = gpr_avl_add(avl, box(163), box(1069));
+  avl = gpr_avl_add(avl, box(283), box(1065), NULL);
+  avl = gpr_avl_add(avl, box(838), box(1066), NULL);
+  avl = gpr_avl_add(avl, box(288), box(1067), NULL);
+  avl = gpr_avl_add(avl, box(950), box(1068), NULL);
+  avl = gpr_avl_add(avl, box(163), box(1069), NULL);
   avl = remove_int(avl, 623);
   avl = remove_int(avl, 769);
-  avl = gpr_avl_add(avl, box(144), box(1072));
-  avl = gpr_avl_add(avl, box(489), box(1073));
+  avl = gpr_avl_add(avl, box(144), box(1072), NULL);
+  avl = gpr_avl_add(avl, box(489), box(1073), NULL);
   avl = remove_int(avl, 15);
-  avl = gpr_avl_add(avl, box(971), box(1075));
+  avl = gpr_avl_add(avl, box(971), box(1075), NULL);
   avl = remove_int(avl, 660);
-  avl = gpr_avl_add(avl, box(255), box(1077));
+  avl = gpr_avl_add(avl, box(255), box(1077), NULL);
   avl = remove_int(avl, 494);
-  avl = gpr_avl_add(avl, box(109), box(1079));
-  avl = gpr_avl_add(avl, box(420), box(1080));
-  avl = gpr_avl_add(avl, box(509), box(1081));
+  avl = gpr_avl_add(avl, box(109), box(1079), NULL);
+  avl = gpr_avl_add(avl, box(420), box(1080), NULL);
+  avl = gpr_avl_add(avl, box(509), box(1081), NULL);
   avl = remove_int(avl, 178);
-  avl = gpr_avl_add(avl, box(216), box(1083));
-  avl = gpr_avl_add(avl, box(707), box(1084));
-  avl = gpr_avl_add(avl, box(411), box(1085));
-  avl = gpr_avl_add(avl, box(352), box(1086));
+  avl = gpr_avl_add(avl, box(216), box(1083), NULL);
+  avl = gpr_avl_add(avl, box(707), box(1084), NULL);
+  avl = gpr_avl_add(avl, box(411), box(1085), NULL);
+  avl = gpr_avl_add(avl, box(352), box(1086), NULL);
   avl = remove_int(avl, 983);
-  avl = gpr_avl_add(avl, box(6), box(1088));
-  avl = gpr_avl_add(avl, box(1014), box(1089));
+  avl = gpr_avl_add(avl, box(6), box(1088), NULL);
+  avl = gpr_avl_add(avl, box(1014), box(1089), NULL);
   avl = remove_int(avl, 98);
   avl = remove_int(avl, 325);
-  avl = gpr_avl_add(avl, box(851), box(1092));
+  avl = gpr_avl_add(avl, box(851), box(1092), NULL);
   avl = remove_int(avl, 553);
-  avl = gpr_avl_add(avl, box(218), box(1094));
-  avl = gpr_avl_add(avl, box(261), box(1095));
+  avl = gpr_avl_add(avl, box(218), box(1094), NULL);
+  avl = gpr_avl_add(avl, box(261), box(1095), NULL);
   avl = remove_int(avl, 31);
-  avl = gpr_avl_add(avl, box(872), box(1097));
+  avl = gpr_avl_add(avl, box(872), box(1097), NULL);
   avl = remove_int(avl, 543);
   avl = remove_int(avl, 314);
   avl = remove_int(avl, 443);
-  avl = gpr_avl_add(avl, box(533), box(1101));
+  avl = gpr_avl_add(avl, box(533), box(1101), NULL);
   avl = remove_int(avl, 881);
   avl = remove_int(avl, 269);
   avl = remove_int(avl, 940);
@@ -2246,114 +2248,114 @@
   avl = remove_int(avl, 773);
   avl = remove_int(avl, 790);
   avl = remove_int(avl, 345);
-  avl = gpr_avl_add(avl, box(965), box(1110));
+  avl = gpr_avl_add(avl, box(965), box(1110), NULL);
   avl = remove_int(avl, 622);
-  avl = gpr_avl_add(avl, box(352), box(1112));
+  avl = gpr_avl_add(avl, box(352), box(1112), NULL);
   avl = remove_int(avl, 182);
-  avl = gpr_avl_add(avl, box(534), box(1114));
-  avl = gpr_avl_add(avl, box(97), box(1115));
-  avl = gpr_avl_add(avl, box(198), box(1116));
+  avl = gpr_avl_add(avl, box(534), box(1114), NULL);
+  avl = gpr_avl_add(avl, box(97), box(1115), NULL);
+  avl = gpr_avl_add(avl, box(198), box(1116), NULL);
   avl = remove_int(avl, 750);
-  avl = gpr_avl_add(avl, box(98), box(1118));
+  avl = gpr_avl_add(avl, box(98), box(1118), NULL);
   avl = remove_int(avl, 943);
-  avl = gpr_avl_add(avl, box(254), box(1120));
-  avl = gpr_avl_add(avl, box(30), box(1121));
+  avl = gpr_avl_add(avl, box(254), box(1120), NULL);
+  avl = gpr_avl_add(avl, box(30), box(1121), NULL);
   avl = remove_int(avl, 14);
   avl = remove_int(avl, 475);
   avl = remove_int(avl, 82);
-  avl = gpr_avl_add(avl, box(789), box(1125));
-  avl = gpr_avl_add(avl, box(402), box(1126));
+  avl = gpr_avl_add(avl, box(789), box(1125), NULL);
+  avl = gpr_avl_add(avl, box(402), box(1126), NULL);
   avl = remove_int(avl, 1019);
-  avl = gpr_avl_add(avl, box(858), box(1128));
-  avl = gpr_avl_add(avl, box(625), box(1129));
+  avl = gpr_avl_add(avl, box(858), box(1128), NULL);
+  avl = gpr_avl_add(avl, box(625), box(1129), NULL);
   avl = remove_int(avl, 675);
   avl = remove_int(avl, 323);
-  avl = gpr_avl_add(avl, box(329), box(1132));
+  avl = gpr_avl_add(avl, box(329), box(1132), NULL);
   avl = remove_int(avl, 929);
   avl = remove_int(avl, 44);
-  avl = gpr_avl_add(avl, box(443), box(1135));
-  avl = gpr_avl_add(avl, box(653), box(1136));
-  avl = gpr_avl_add(avl, box(750), box(1137));
-  avl = gpr_avl_add(avl, box(252), box(1138));
-  avl = gpr_avl_add(avl, box(449), box(1139));
+  avl = gpr_avl_add(avl, box(443), box(1135), NULL);
+  avl = gpr_avl_add(avl, box(653), box(1136), NULL);
+  avl = gpr_avl_add(avl, box(750), box(1137), NULL);
+  avl = gpr_avl_add(avl, box(252), box(1138), NULL);
+  avl = gpr_avl_add(avl, box(449), box(1139), NULL);
   avl = remove_int(avl, 1022);
   avl = remove_int(avl, 357);
   avl = remove_int(avl, 602);
   avl = remove_int(avl, 131);
-  avl = gpr_avl_add(avl, box(531), box(1144));
+  avl = gpr_avl_add(avl, box(531), box(1144), NULL);
   avl = remove_int(avl, 806);
-  avl = gpr_avl_add(avl, box(455), box(1146));
+  avl = gpr_avl_add(avl, box(455), box(1146), NULL);
   avl = remove_int(avl, 31);
-  avl = gpr_avl_add(avl, box(154), box(1148));
-  avl = gpr_avl_add(avl, box(189), box(1149));
+  avl = gpr_avl_add(avl, box(154), box(1148), NULL);
+  avl = gpr_avl_add(avl, box(189), box(1149), NULL);
   avl = remove_int(avl, 786);
-  avl = gpr_avl_add(avl, box(496), box(1151));
-  avl = gpr_avl_add(avl, box(81), box(1152));
-  avl = gpr_avl_add(avl, box(59), box(1153));
+  avl = gpr_avl_add(avl, box(496), box(1151), NULL);
+  avl = gpr_avl_add(avl, box(81), box(1152), NULL);
+  avl = gpr_avl_add(avl, box(59), box(1153), NULL);
   avl = remove_int(avl, 424);
   avl = remove_int(avl, 668);
-  avl = gpr_avl_add(avl, box(723), box(1156));
-  avl = gpr_avl_add(avl, box(822), box(1157));
-  avl = gpr_avl_add(avl, box(354), box(1158));
+  avl = gpr_avl_add(avl, box(723), box(1156), NULL);
+  avl = gpr_avl_add(avl, box(822), box(1157), NULL);
+  avl = gpr_avl_add(avl, box(354), box(1158), NULL);
   avl = remove_int(avl, 738);
-  avl = gpr_avl_add(avl, box(686), box(1160));
-  avl = gpr_avl_add(avl, box(43), box(1161));
-  avl = gpr_avl_add(avl, box(625), box(1162));
-  avl = gpr_avl_add(avl, box(902), box(1163));
-  avl = gpr_avl_add(avl, box(12), box(1164));
-  avl = gpr_avl_add(avl, box(977), box(1165));
-  avl = gpr_avl_add(avl, box(699), box(1166));
-  avl = gpr_avl_add(avl, box(189), box(1167));
+  avl = gpr_avl_add(avl, box(686), box(1160), NULL);
+  avl = gpr_avl_add(avl, box(43), box(1161), NULL);
+  avl = gpr_avl_add(avl, box(625), box(1162), NULL);
+  avl = gpr_avl_add(avl, box(902), box(1163), NULL);
+  avl = gpr_avl_add(avl, box(12), box(1164), NULL);
+  avl = gpr_avl_add(avl, box(977), box(1165), NULL);
+  avl = gpr_avl_add(avl, box(699), box(1166), NULL);
+  avl = gpr_avl_add(avl, box(189), box(1167), NULL);
   avl = remove_int(avl, 672);
   avl = remove_int(avl, 90);
   avl = remove_int(avl, 757);
   avl = remove_int(avl, 494);
-  avl = gpr_avl_add(avl, box(759), box(1172));
+  avl = gpr_avl_add(avl, box(759), box(1172), NULL);
   avl = remove_int(avl, 758);
   avl = remove_int(avl, 222);
-  avl = gpr_avl_add(avl, box(975), box(1175));
+  avl = gpr_avl_add(avl, box(975), box(1175), NULL);
   avl = remove_int(avl, 993);
-  avl = gpr_avl_add(avl, box(2), box(1177));
-  avl = gpr_avl_add(avl, box(70), box(1178));
+  avl = gpr_avl_add(avl, box(2), box(1177), NULL);
+  avl = gpr_avl_add(avl, box(70), box(1178), NULL);
   avl = remove_int(avl, 350);
   avl = remove_int(avl, 972);
   avl = remove_int(avl, 880);
-  avl = gpr_avl_add(avl, box(753), box(1182));
+  avl = gpr_avl_add(avl, box(753), box(1182), NULL);
   avl = remove_int(avl, 404);
-  avl = gpr_avl_add(avl, box(294), box(1184));
+  avl = gpr_avl_add(avl, box(294), box(1184), NULL);
   avl = remove_int(avl, 474);
-  avl = gpr_avl_add(avl, box(228), box(1186));
-  avl = gpr_avl_add(avl, box(484), box(1187));
+  avl = gpr_avl_add(avl, box(228), box(1186), NULL);
+  avl = gpr_avl_add(avl, box(484), box(1187), NULL);
   avl = remove_int(avl, 238);
   avl = remove_int(avl, 53);
   avl = remove_int(avl, 691);
-  avl = gpr_avl_add(avl, box(345), box(1191));
+  avl = gpr_avl_add(avl, box(345), box(1191), NULL);
   avl = remove_int(avl, 0);
-  avl = gpr_avl_add(avl, box(230), box(1193));
+  avl = gpr_avl_add(avl, box(230), box(1193), NULL);
   avl = remove_int(avl, 227);
   avl = remove_int(avl, 152);
-  avl = gpr_avl_add(avl, box(884), box(1196));
+  avl = gpr_avl_add(avl, box(884), box(1196), NULL);
   avl = remove_int(avl, 823);
   avl = remove_int(avl, 53);
-  avl = gpr_avl_add(avl, box(1015), box(1199));
-  avl = gpr_avl_add(avl, box(697), box(1200));
-  avl = gpr_avl_add(avl, box(376), box(1201));
+  avl = gpr_avl_add(avl, box(1015), box(1199), NULL);
+  avl = gpr_avl_add(avl, box(697), box(1200), NULL);
+  avl = gpr_avl_add(avl, box(376), box(1201), NULL);
   avl = remove_int(avl, 411);
-  avl = gpr_avl_add(avl, box(888), box(1203));
+  avl = gpr_avl_add(avl, box(888), box(1203), NULL);
   avl = remove_int(avl, 55);
-  avl = gpr_avl_add(avl, box(85), box(1205));
+  avl = gpr_avl_add(avl, box(85), box(1205), NULL);
   avl = remove_int(avl, 947);
   avl = remove_int(avl, 382);
   avl = remove_int(avl, 777);
-  avl = gpr_avl_add(avl, box(1017), box(1209));
-  avl = gpr_avl_add(avl, box(169), box(1210));
-  avl = gpr_avl_add(avl, box(156), box(1211));
+  avl = gpr_avl_add(avl, box(1017), box(1209), NULL);
+  avl = gpr_avl_add(avl, box(169), box(1210), NULL);
+  avl = gpr_avl_add(avl, box(156), box(1211), NULL);
   avl = remove_int(avl, 153);
   avl = remove_int(avl, 642);
   avl = remove_int(avl, 158);
-  avl = gpr_avl_add(avl, box(554), box(1215));
-  avl = gpr_avl_add(avl, box(76), box(1216));
-  avl = gpr_avl_add(avl, box(756), box(1217));
+  avl = gpr_avl_add(avl, box(554), box(1215), NULL);
+  avl = gpr_avl_add(avl, box(76), box(1216), NULL);
+  avl = gpr_avl_add(avl, box(756), box(1217), NULL);
   avl = remove_int(avl, 767);
   avl = remove_int(avl, 112);
   avl = remove_int(avl, 539);
@@ -2362,37 +2364,37 @@
   avl = remove_int(avl, 385);
   avl = remove_int(avl, 514);
   avl = remove_int(avl, 362);
-  avl = gpr_avl_add(avl, box(523), box(1226));
-  avl = gpr_avl_add(avl, box(712), box(1227));
-  avl = gpr_avl_add(avl, box(474), box(1228));
-  avl = gpr_avl_add(avl, box(882), box(1229));
-  avl = gpr_avl_add(avl, box(965), box(1230));
+  avl = gpr_avl_add(avl, box(523), box(1226), NULL);
+  avl = gpr_avl_add(avl, box(712), box(1227), NULL);
+  avl = gpr_avl_add(avl, box(474), box(1228), NULL);
+  avl = gpr_avl_add(avl, box(882), box(1229), NULL);
+  avl = gpr_avl_add(avl, box(965), box(1230), NULL);
   avl = remove_int(avl, 464);
-  avl = gpr_avl_add(avl, box(319), box(1232));
-  avl = gpr_avl_add(avl, box(504), box(1233));
+  avl = gpr_avl_add(avl, box(319), box(1232), NULL);
+  avl = gpr_avl_add(avl, box(504), box(1233), NULL);
   avl = remove_int(avl, 818);
-  avl = gpr_avl_add(avl, box(884), box(1235));
-  avl = gpr_avl_add(avl, box(813), box(1236));
-  avl = gpr_avl_add(avl, box(795), box(1237));
+  avl = gpr_avl_add(avl, box(884), box(1235), NULL);
+  avl = gpr_avl_add(avl, box(813), box(1236), NULL);
+  avl = gpr_avl_add(avl, box(795), box(1237), NULL);
   avl = remove_int(avl, 306);
-  avl = gpr_avl_add(avl, box(799), box(1239));
+  avl = gpr_avl_add(avl, box(799), box(1239), NULL);
   avl = remove_int(avl, 534);
-  avl = gpr_avl_add(avl, box(480), box(1241));
-  avl = gpr_avl_add(avl, box(656), box(1242));
-  avl = gpr_avl_add(avl, box(709), box(1243));
-  avl = gpr_avl_add(avl, box(500), box(1244));
+  avl = gpr_avl_add(avl, box(480), box(1241), NULL);
+  avl = gpr_avl_add(avl, box(656), box(1242), NULL);
+  avl = gpr_avl_add(avl, box(709), box(1243), NULL);
+  avl = gpr_avl_add(avl, box(500), box(1244), NULL);
   avl = remove_int(avl, 740);
-  avl = gpr_avl_add(avl, box(980), box(1246));
-  avl = gpr_avl_add(avl, box(458), box(1247));
+  avl = gpr_avl_add(avl, box(980), box(1246), NULL);
+  avl = gpr_avl_add(avl, box(458), box(1247), NULL);
   avl = remove_int(avl, 377);
   avl = remove_int(avl, 338);
-  avl = gpr_avl_add(avl, box(554), box(1250));
-  avl = gpr_avl_add(avl, box(504), box(1251));
-  avl = gpr_avl_add(avl, box(603), box(1252));
-  avl = gpr_avl_add(avl, box(761), box(1253));
+  avl = gpr_avl_add(avl, box(554), box(1250), NULL);
+  avl = gpr_avl_add(avl, box(504), box(1251), NULL);
+  avl = gpr_avl_add(avl, box(603), box(1252), NULL);
+  avl = gpr_avl_add(avl, box(761), box(1253), NULL);
   avl = remove_int(avl, 431);
-  avl = gpr_avl_add(avl, box(707), box(1255));
-  avl = gpr_avl_add(avl, box(673), box(1256));
+  avl = gpr_avl_add(avl, box(707), box(1255), NULL);
+  avl = gpr_avl_add(avl, box(673), box(1256), NULL);
   avl = remove_int(avl, 998);
   avl = remove_int(avl, 332);
   avl = remove_int(avl, 413);
@@ -2400,448 +2402,448 @@
   avl = remove_int(avl, 249);
   avl = remove_int(avl, 309);
   avl = remove_int(avl, 459);
-  avl = gpr_avl_add(avl, box(645), box(1264));
+  avl = gpr_avl_add(avl, box(645), box(1264), NULL);
   avl = remove_int(avl, 858);
   avl = remove_int(avl, 997);
-  avl = gpr_avl_add(avl, box(519), box(1267));
+  avl = gpr_avl_add(avl, box(519), box(1267), NULL);
   avl = remove_int(avl, 614);
   avl = remove_int(avl, 462);
   avl = remove_int(avl, 792);
-  avl = gpr_avl_add(avl, box(987), box(1271));
-  avl = gpr_avl_add(avl, box(309), box(1272));
+  avl = gpr_avl_add(avl, box(987), box(1271), NULL);
+  avl = gpr_avl_add(avl, box(309), box(1272), NULL);
   avl = remove_int(avl, 747);
-  avl = gpr_avl_add(avl, box(621), box(1274));
-  avl = gpr_avl_add(avl, box(450), box(1275));
+  avl = gpr_avl_add(avl, box(621), box(1274), NULL);
+  avl = gpr_avl_add(avl, box(450), box(1275), NULL);
   avl = remove_int(avl, 265);
   avl = remove_int(avl, 8);
   avl = remove_int(avl, 383);
-  avl = gpr_avl_add(avl, box(238), box(1279));
+  avl = gpr_avl_add(avl, box(238), box(1279), NULL);
   avl = remove_int(avl, 241);
-  avl = gpr_avl_add(avl, box(180), box(1281));
-  avl = gpr_avl_add(avl, box(411), box(1282));
-  avl = gpr_avl_add(avl, box(791), box(1283));
-  avl = gpr_avl_add(avl, box(955), box(1284));
+  avl = gpr_avl_add(avl, box(180), box(1281), NULL);
+  avl = gpr_avl_add(avl, box(411), box(1282), NULL);
+  avl = gpr_avl_add(avl, box(791), box(1283), NULL);
+  avl = gpr_avl_add(avl, box(955), box(1284), NULL);
   avl = remove_int(avl, 24);
   avl = remove_int(avl, 375);
-  avl = gpr_avl_add(avl, box(140), box(1287));
+  avl = gpr_avl_add(avl, box(140), box(1287), NULL);
   avl = remove_int(avl, 949);
-  avl = gpr_avl_add(avl, box(301), box(1289));
-  avl = gpr_avl_add(avl, box(0), box(1290));
+  avl = gpr_avl_add(avl, box(301), box(1289), NULL);
+  avl = gpr_avl_add(avl, box(0), box(1290), NULL);
   avl = remove_int(avl, 371);
   avl = remove_int(avl, 427);
   avl = remove_int(avl, 841);
   avl = remove_int(avl, 847);
-  avl = gpr_avl_add(avl, box(814), box(1295));
-  avl = gpr_avl_add(avl, box(127), box(1296));
-  avl = gpr_avl_add(avl, box(279), box(1297));
+  avl = gpr_avl_add(avl, box(814), box(1295), NULL);
+  avl = gpr_avl_add(avl, box(127), box(1296), NULL);
+  avl = gpr_avl_add(avl, box(279), box(1297), NULL);
   avl = remove_int(avl, 669);
   avl = remove_int(avl, 541);
   avl = remove_int(avl, 275);
   avl = remove_int(avl, 299);
   avl = remove_int(avl, 552);
-  avl = gpr_avl_add(avl, box(310), box(1303));
-  avl = gpr_avl_add(avl, box(304), box(1304));
-  avl = gpr_avl_add(avl, box(1), box(1305));
-  avl = gpr_avl_add(avl, box(339), box(1306));
+  avl = gpr_avl_add(avl, box(310), box(1303), NULL);
+  avl = gpr_avl_add(avl, box(304), box(1304), NULL);
+  avl = gpr_avl_add(avl, box(1), box(1305), NULL);
+  avl = gpr_avl_add(avl, box(339), box(1306), NULL);
   avl = remove_int(avl, 570);
   avl = remove_int(avl, 752);
   avl = remove_int(avl, 552);
   avl = remove_int(avl, 442);
   avl = remove_int(avl, 639);
-  avl = gpr_avl_add(avl, box(313), box(1312));
+  avl = gpr_avl_add(avl, box(313), box(1312), NULL);
   avl = remove_int(avl, 85);
-  avl = gpr_avl_add(avl, box(964), box(1314));
-  avl = gpr_avl_add(avl, box(559), box(1315));
+  avl = gpr_avl_add(avl, box(964), box(1314), NULL);
+  avl = gpr_avl_add(avl, box(559), box(1315), NULL);
   avl = remove_int(avl, 167);
-  avl = gpr_avl_add(avl, box(866), box(1317));
+  avl = gpr_avl_add(avl, box(866), box(1317), NULL);
   avl = remove_int(avl, 275);
-  avl = gpr_avl_add(avl, box(173), box(1319));
-  avl = gpr_avl_add(avl, box(765), box(1320));
+  avl = gpr_avl_add(avl, box(173), box(1319), NULL);
+  avl = gpr_avl_add(avl, box(765), box(1320), NULL);
   avl = remove_int(avl, 883);
-  avl = gpr_avl_add(avl, box(547), box(1322));
-  avl = gpr_avl_add(avl, box(847), box(1323));
+  avl = gpr_avl_add(avl, box(547), box(1322), NULL);
+  avl = gpr_avl_add(avl, box(847), box(1323), NULL);
   avl = remove_int(avl, 817);
   avl = remove_int(avl, 850);
   avl = remove_int(avl, 718);
-  avl = gpr_avl_add(avl, box(806), box(1327));
-  avl = gpr_avl_add(avl, box(360), box(1328));
+  avl = gpr_avl_add(avl, box(806), box(1327), NULL);
+  avl = gpr_avl_add(avl, box(360), box(1328), NULL);
   avl = remove_int(avl, 991);
-  avl = gpr_avl_add(avl, box(493), box(1330));
+  avl = gpr_avl_add(avl, box(493), box(1330), NULL);
   avl = remove_int(avl, 516);
-  avl = gpr_avl_add(avl, box(361), box(1332));
+  avl = gpr_avl_add(avl, box(361), box(1332), NULL);
   avl = remove_int(avl, 355);
-  avl = gpr_avl_add(avl, box(512), box(1334));
-  avl = gpr_avl_add(avl, box(191), box(1335));
+  avl = gpr_avl_add(avl, box(512), box(1334), NULL);
+  avl = gpr_avl_add(avl, box(191), box(1335), NULL);
   avl = remove_int(avl, 703);
-  avl = gpr_avl_add(avl, box(333), box(1337));
+  avl = gpr_avl_add(avl, box(333), box(1337), NULL);
   avl = remove_int(avl, 481);
-  avl = gpr_avl_add(avl, box(501), box(1339));
+  avl = gpr_avl_add(avl, box(501), box(1339), NULL);
   avl = remove_int(avl, 532);
   avl = remove_int(avl, 510);
-  avl = gpr_avl_add(avl, box(793), box(1342));
-  avl = gpr_avl_add(avl, box(234), box(1343));
+  avl = gpr_avl_add(avl, box(793), box(1342), NULL);
+  avl = gpr_avl_add(avl, box(234), box(1343), NULL);
   avl = remove_int(avl, 159);
   avl = remove_int(avl, 429);
   avl = remove_int(avl, 728);
   avl = remove_int(avl, 288);
-  avl = gpr_avl_add(avl, box(281), box(1348));
-  avl = gpr_avl_add(avl, box(702), box(1349));
-  avl = gpr_avl_add(avl, box(149), box(1350));
+  avl = gpr_avl_add(avl, box(281), box(1348), NULL);
+  avl = gpr_avl_add(avl, box(702), box(1349), NULL);
+  avl = gpr_avl_add(avl, box(149), box(1350), NULL);
   avl = remove_int(avl, 22);
   avl = remove_int(avl, 944);
   avl = remove_int(avl, 55);
   avl = remove_int(avl, 512);
   avl = remove_int(avl, 676);
   avl = remove_int(avl, 884);
-  avl = gpr_avl_add(avl, box(246), box(1357));
-  avl = gpr_avl_add(avl, box(455), box(1358));
+  avl = gpr_avl_add(avl, box(246), box(1357), NULL);
+  avl = gpr_avl_add(avl, box(455), box(1358), NULL);
   avl = remove_int(avl, 782);
   avl = remove_int(avl, 682);
-  avl = gpr_avl_add(avl, box(243), box(1361));
-  avl = gpr_avl_add(avl, box(109), box(1362));
-  avl = gpr_avl_add(avl, box(452), box(1363));
+  avl = gpr_avl_add(avl, box(243), box(1361), NULL);
+  avl = gpr_avl_add(avl, box(109), box(1362), NULL);
+  avl = gpr_avl_add(avl, box(452), box(1363), NULL);
   avl = remove_int(avl, 151);
-  avl = gpr_avl_add(avl, box(159), box(1365));
+  avl = gpr_avl_add(avl, box(159), box(1365), NULL);
   avl = remove_int(avl, 1023);
-  avl = gpr_avl_add(avl, box(129), box(1367));
-  avl = gpr_avl_add(avl, box(537), box(1368));
+  avl = gpr_avl_add(avl, box(129), box(1367), NULL);
+  avl = gpr_avl_add(avl, box(537), box(1368), NULL);
   avl = remove_int(avl, 321);
-  avl = gpr_avl_add(avl, box(740), box(1370));
+  avl = gpr_avl_add(avl, box(740), box(1370), NULL);
   avl = remove_int(avl, 45);
   avl = remove_int(avl, 136);
-  avl = gpr_avl_add(avl, box(229), box(1373));
+  avl = gpr_avl_add(avl, box(229), box(1373), NULL);
   avl = remove_int(avl, 772);
-  avl = gpr_avl_add(avl, box(181), box(1375));
+  avl = gpr_avl_add(avl, box(181), box(1375), NULL);
   avl = remove_int(avl, 175);
-  avl = gpr_avl_add(avl, box(817), box(1377));
+  avl = gpr_avl_add(avl, box(817), box(1377), NULL);
   avl = remove_int(avl, 956);
-  avl = gpr_avl_add(avl, box(675), box(1379));
-  avl = gpr_avl_add(avl, box(375), box(1380));
+  avl = gpr_avl_add(avl, box(675), box(1379), NULL);
+  avl = gpr_avl_add(avl, box(375), box(1380), NULL);
   avl = remove_int(avl, 384);
-  avl = gpr_avl_add(avl, box(1016), box(1382));
+  avl = gpr_avl_add(avl, box(1016), box(1382), NULL);
   avl = remove_int(avl, 295);
   avl = remove_int(avl, 697);
   avl = remove_int(avl, 554);
   avl = remove_int(avl, 590);
   avl = remove_int(avl, 1014);
-  avl = gpr_avl_add(avl, box(890), box(1388));
-  avl = gpr_avl_add(avl, box(293), box(1389));
+  avl = gpr_avl_add(avl, box(890), box(1388), NULL);
+  avl = gpr_avl_add(avl, box(293), box(1389), NULL);
   avl = remove_int(avl, 207);
   avl = remove_int(avl, 46);
-  avl = gpr_avl_add(avl, box(899), box(1392));
-  avl = gpr_avl_add(avl, box(666), box(1393));
-  avl = gpr_avl_add(avl, box(85), box(1394));
-  avl = gpr_avl_add(avl, box(914), box(1395));
-  avl = gpr_avl_add(avl, box(128), box(1396));
-  avl = gpr_avl_add(avl, box(835), box(1397));
-  avl = gpr_avl_add(avl, box(787), box(1398));
-  avl = gpr_avl_add(avl, box(649), box(1399));
-  avl = gpr_avl_add(avl, box(723), box(1400));
+  avl = gpr_avl_add(avl, box(899), box(1392), NULL);
+  avl = gpr_avl_add(avl, box(666), box(1393), NULL);
+  avl = gpr_avl_add(avl, box(85), box(1394), NULL);
+  avl = gpr_avl_add(avl, box(914), box(1395), NULL);
+  avl = gpr_avl_add(avl, box(128), box(1396), NULL);
+  avl = gpr_avl_add(avl, box(835), box(1397), NULL);
+  avl = gpr_avl_add(avl, box(787), box(1398), NULL);
+  avl = gpr_avl_add(avl, box(649), box(1399), NULL);
+  avl = gpr_avl_add(avl, box(723), box(1400), NULL);
   avl = remove_int(avl, 874);
-  avl = gpr_avl_add(avl, box(778), box(1402));
-  avl = gpr_avl_add(avl, box(1015), box(1403));
-  avl = gpr_avl_add(avl, box(59), box(1404));
-  avl = gpr_avl_add(avl, box(259), box(1405));
-  avl = gpr_avl_add(avl, box(758), box(1406));
+  avl = gpr_avl_add(avl, box(778), box(1402), NULL);
+  avl = gpr_avl_add(avl, box(1015), box(1403), NULL);
+  avl = gpr_avl_add(avl, box(59), box(1404), NULL);
+  avl = gpr_avl_add(avl, box(259), box(1405), NULL);
+  avl = gpr_avl_add(avl, box(758), box(1406), NULL);
   avl = remove_int(avl, 648);
-  avl = gpr_avl_add(avl, box(145), box(1408));
-  avl = gpr_avl_add(avl, box(440), box(1409));
+  avl = gpr_avl_add(avl, box(145), box(1408), NULL);
+  avl = gpr_avl_add(avl, box(440), box(1409), NULL);
   avl = remove_int(avl, 608);
   avl = remove_int(avl, 690);
-  avl = gpr_avl_add(avl, box(605), box(1412));
+  avl = gpr_avl_add(avl, box(605), box(1412), NULL);
   avl = remove_int(avl, 856);
   avl = remove_int(avl, 608);
-  avl = gpr_avl_add(avl, box(829), box(1415));
-  avl = gpr_avl_add(avl, box(660), box(1416));
+  avl = gpr_avl_add(avl, box(829), box(1415), NULL);
+  avl = gpr_avl_add(avl, box(660), box(1416), NULL);
   avl = remove_int(avl, 596);
-  avl = gpr_avl_add(avl, box(519), box(1418));
-  avl = gpr_avl_add(avl, box(35), box(1419));
-  avl = gpr_avl_add(avl, box(871), box(1420));
+  avl = gpr_avl_add(avl, box(519), box(1418), NULL);
+  avl = gpr_avl_add(avl, box(35), box(1419), NULL);
+  avl = gpr_avl_add(avl, box(871), box(1420), NULL);
   avl = remove_int(avl, 845);
-  avl = gpr_avl_add(avl, box(600), box(1422));
-  avl = gpr_avl_add(avl, box(215), box(1423));
+  avl = gpr_avl_add(avl, box(600), box(1422), NULL);
+  avl = gpr_avl_add(avl, box(215), box(1423), NULL);
   avl = remove_int(avl, 761);
-  avl = gpr_avl_add(avl, box(975), box(1425));
+  avl = gpr_avl_add(avl, box(975), box(1425), NULL);
   avl = remove_int(avl, 987);
-  avl = gpr_avl_add(avl, box(58), box(1427));
+  avl = gpr_avl_add(avl, box(58), box(1427), NULL);
   avl = remove_int(avl, 119);
-  avl = gpr_avl_add(avl, box(937), box(1429));
-  avl = gpr_avl_add(avl, box(372), box(1430));
-  avl = gpr_avl_add(avl, box(11), box(1431));
-  avl = gpr_avl_add(avl, box(398), box(1432));
-  avl = gpr_avl_add(avl, box(423), box(1433));
+  avl = gpr_avl_add(avl, box(937), box(1429), NULL);
+  avl = gpr_avl_add(avl, box(372), box(1430), NULL);
+  avl = gpr_avl_add(avl, box(11), box(1431), NULL);
+  avl = gpr_avl_add(avl, box(398), box(1432), NULL);
+  avl = gpr_avl_add(avl, box(423), box(1433), NULL);
   avl = remove_int(avl, 171);
-  avl = gpr_avl_add(avl, box(473), box(1435));
+  avl = gpr_avl_add(avl, box(473), box(1435), NULL);
   avl = remove_int(avl, 752);
   avl = remove_int(avl, 625);
   avl = remove_int(avl, 764);
   avl = remove_int(avl, 49);
-  avl = gpr_avl_add(avl, box(472), box(1440));
+  avl = gpr_avl_add(avl, box(472), box(1440), NULL);
   avl = remove_int(avl, 847);
   avl = remove_int(avl, 642);
   avl = remove_int(avl, 1004);
   avl = remove_int(avl, 795);
   avl = remove_int(avl, 465);
-  avl = gpr_avl_add(avl, box(636), box(1446));
+  avl = gpr_avl_add(avl, box(636), box(1446), NULL);
   avl = remove_int(avl, 152);
-  avl = gpr_avl_add(avl, box(61), box(1448));
+  avl = gpr_avl_add(avl, box(61), box(1448), NULL);
   avl = remove_int(avl, 929);
   avl = remove_int(avl, 9);
-  avl = gpr_avl_add(avl, box(251), box(1451));
-  avl = gpr_avl_add(avl, box(672), box(1452));
-  avl = gpr_avl_add(avl, box(66), box(1453));
+  avl = gpr_avl_add(avl, box(251), box(1451), NULL);
+  avl = gpr_avl_add(avl, box(672), box(1452), NULL);
+  avl = gpr_avl_add(avl, box(66), box(1453), NULL);
   avl = remove_int(avl, 693);
   avl = remove_int(avl, 914);
   avl = remove_int(avl, 116);
   avl = remove_int(avl, 577);
-  avl = gpr_avl_add(avl, box(618), box(1458));
-  avl = gpr_avl_add(avl, box(495), box(1459));
+  avl = gpr_avl_add(avl, box(618), box(1458), NULL);
+  avl = gpr_avl_add(avl, box(495), box(1459), NULL);
   avl = remove_int(avl, 450);
-  avl = gpr_avl_add(avl, box(533), box(1461));
-  avl = gpr_avl_add(avl, box(414), box(1462));
+  avl = gpr_avl_add(avl, box(533), box(1461), NULL);
+  avl = gpr_avl_add(avl, box(414), box(1462), NULL);
   avl = remove_int(avl, 74);
   avl = remove_int(avl, 236);
-  avl = gpr_avl_add(avl, box(707), box(1465));
-  avl = gpr_avl_add(avl, box(357), box(1466));
-  avl = gpr_avl_add(avl, box(1007), box(1467));
-  avl = gpr_avl_add(avl, box(811), box(1468));
-  avl = gpr_avl_add(avl, box(418), box(1469));
-  avl = gpr_avl_add(avl, box(164), box(1470));
-  avl = gpr_avl_add(avl, box(622), box(1471));
+  avl = gpr_avl_add(avl, box(707), box(1465), NULL);
+  avl = gpr_avl_add(avl, box(357), box(1466), NULL);
+  avl = gpr_avl_add(avl, box(1007), box(1467), NULL);
+  avl = gpr_avl_add(avl, box(811), box(1468), NULL);
+  avl = gpr_avl_add(avl, box(418), box(1469), NULL);
+  avl = gpr_avl_add(avl, box(164), box(1470), NULL);
+  avl = gpr_avl_add(avl, box(622), box(1471), NULL);
   avl = remove_int(avl, 22);
   avl = remove_int(avl, 14);
   avl = remove_int(avl, 732);
   avl = remove_int(avl, 7);
   avl = remove_int(avl, 447);
-  avl = gpr_avl_add(avl, box(221), box(1477));
-  avl = gpr_avl_add(avl, box(202), box(1478));
-  avl = gpr_avl_add(avl, box(312), box(1479));
+  avl = gpr_avl_add(avl, box(221), box(1477), NULL);
+  avl = gpr_avl_add(avl, box(202), box(1478), NULL);
+  avl = gpr_avl_add(avl, box(312), box(1479), NULL);
   avl = remove_int(avl, 274);
-  avl = gpr_avl_add(avl, box(684), box(1481));
-  avl = gpr_avl_add(avl, box(954), box(1482));
-  avl = gpr_avl_add(avl, box(637), box(1483));
+  avl = gpr_avl_add(avl, box(684), box(1481), NULL);
+  avl = gpr_avl_add(avl, box(954), box(1482), NULL);
+  avl = gpr_avl_add(avl, box(637), box(1483), NULL);
   avl = remove_int(avl, 716);
-  avl = gpr_avl_add(avl, box(198), box(1485));
+  avl = gpr_avl_add(avl, box(198), box(1485), NULL);
   avl = remove_int(avl, 340);
   avl = remove_int(avl, 137);
   avl = remove_int(avl, 995);
   avl = remove_int(avl, 1004);
-  avl = gpr_avl_add(avl, box(661), box(1490));
-  avl = gpr_avl_add(avl, box(862), box(1491));
+  avl = gpr_avl_add(avl, box(661), box(1490), NULL);
+  avl = gpr_avl_add(avl, box(862), box(1491), NULL);
   avl = remove_int(avl, 527);
-  avl = gpr_avl_add(avl, box(945), box(1493));
+  avl = gpr_avl_add(avl, box(945), box(1493), NULL);
   avl = remove_int(avl, 355);
   avl = remove_int(avl, 144);
-  avl = gpr_avl_add(avl, box(229), box(1496));
-  avl = gpr_avl_add(avl, box(237), box(1497));
+  avl = gpr_avl_add(avl, box(229), box(1496), NULL);
+  avl = gpr_avl_add(avl, box(237), box(1497), NULL);
   avl = remove_int(avl, 471);
   avl = remove_int(avl, 901);
-  avl = gpr_avl_add(avl, box(905), box(1500));
+  avl = gpr_avl_add(avl, box(905), box(1500), NULL);
   avl = remove_int(avl, 19);
   avl = remove_int(avl, 896);
   avl = remove_int(avl, 585);
   avl = remove_int(avl, 308);
-  avl = gpr_avl_add(avl, box(547), box(1505));
-  avl = gpr_avl_add(avl, box(552), box(1506));
-  avl = gpr_avl_add(avl, box(30), box(1507));
-  avl = gpr_avl_add(avl, box(445), box(1508));
+  avl = gpr_avl_add(avl, box(547), box(1505), NULL);
+  avl = gpr_avl_add(avl, box(552), box(1506), NULL);
+  avl = gpr_avl_add(avl, box(30), box(1507), NULL);
+  avl = gpr_avl_add(avl, box(445), box(1508), NULL);
   avl = remove_int(avl, 785);
   avl = remove_int(avl, 185);
-  avl = gpr_avl_add(avl, box(405), box(1511));
-  avl = gpr_avl_add(avl, box(733), box(1512));
-  avl = gpr_avl_add(avl, box(573), box(1513));
-  avl = gpr_avl_add(avl, box(492), box(1514));
-  avl = gpr_avl_add(avl, box(343), box(1515));
-  avl = gpr_avl_add(avl, box(527), box(1516));
-  avl = gpr_avl_add(avl, box(596), box(1517));
-  avl = gpr_avl_add(avl, box(519), box(1518));
+  avl = gpr_avl_add(avl, box(405), box(1511), NULL);
+  avl = gpr_avl_add(avl, box(733), box(1512), NULL);
+  avl = gpr_avl_add(avl, box(573), box(1513), NULL);
+  avl = gpr_avl_add(avl, box(492), box(1514), NULL);
+  avl = gpr_avl_add(avl, box(343), box(1515), NULL);
+  avl = gpr_avl_add(avl, box(527), box(1516), NULL);
+  avl = gpr_avl_add(avl, box(596), box(1517), NULL);
+  avl = gpr_avl_add(avl, box(519), box(1518), NULL);
   avl = remove_int(avl, 243);
   avl = remove_int(avl, 722);
-  avl = gpr_avl_add(avl, box(772), box(1521));
+  avl = gpr_avl_add(avl, box(772), box(1521), NULL);
   avl = remove_int(avl, 152);
   avl = remove_int(avl, 305);
-  avl = gpr_avl_add(avl, box(754), box(1524));
-  avl = gpr_avl_add(avl, box(373), box(1525));
+  avl = gpr_avl_add(avl, box(754), box(1524), NULL);
+  avl = gpr_avl_add(avl, box(373), box(1525), NULL);
   avl = remove_int(avl, 995);
-  avl = gpr_avl_add(avl, box(329), box(1527));
+  avl = gpr_avl_add(avl, box(329), box(1527), NULL);
   avl = remove_int(avl, 397);
-  avl = gpr_avl_add(avl, box(884), box(1529));
+  avl = gpr_avl_add(avl, box(884), box(1529), NULL);
   avl = remove_int(avl, 329);
   avl = remove_int(avl, 240);
-  avl = gpr_avl_add(avl, box(566), box(1532));
-  avl = gpr_avl_add(avl, box(232), box(1533));
+  avl = gpr_avl_add(avl, box(566), box(1532), NULL);
+  avl = gpr_avl_add(avl, box(232), box(1533), NULL);
   avl = remove_int(avl, 993);
-  avl = gpr_avl_add(avl, box(888), box(1535));
+  avl = gpr_avl_add(avl, box(888), box(1535), NULL);
   avl = remove_int(avl, 242);
-  avl = gpr_avl_add(avl, box(941), box(1537));
+  avl = gpr_avl_add(avl, box(941), box(1537), NULL);
   avl = remove_int(avl, 415);
-  avl = gpr_avl_add(avl, box(992), box(1539));
+  avl = gpr_avl_add(avl, box(992), box(1539), NULL);
   avl = remove_int(avl, 289);
-  avl = gpr_avl_add(avl, box(60), box(1541));
-  avl = gpr_avl_add(avl, box(97), box(1542));
+  avl = gpr_avl_add(avl, box(60), box(1541), NULL);
+  avl = gpr_avl_add(avl, box(97), box(1542), NULL);
   avl = remove_int(avl, 965);
   avl = remove_int(avl, 267);
   avl = remove_int(avl, 360);
-  avl = gpr_avl_add(avl, box(5), box(1546));
+  avl = gpr_avl_add(avl, box(5), box(1546), NULL);
   avl = remove_int(avl, 429);
-  avl = gpr_avl_add(avl, box(412), box(1548));
+  avl = gpr_avl_add(avl, box(412), box(1548), NULL);
   avl = remove_int(avl, 632);
   avl = remove_int(avl, 113);
-  avl = gpr_avl_add(avl, box(48), box(1551));
-  avl = gpr_avl_add(avl, box(108), box(1552));
-  avl = gpr_avl_add(avl, box(750), box(1553));
+  avl = gpr_avl_add(avl, box(48), box(1551), NULL);
+  avl = gpr_avl_add(avl, box(108), box(1552), NULL);
+  avl = gpr_avl_add(avl, box(750), box(1553), NULL);
   avl = remove_int(avl, 188);
-  avl = gpr_avl_add(avl, box(668), box(1555));
+  avl = gpr_avl_add(avl, box(668), box(1555), NULL);
   avl = remove_int(avl, 37);
   avl = remove_int(avl, 737);
-  avl = gpr_avl_add(avl, box(93), box(1558));
-  avl = gpr_avl_add(avl, box(628), box(1559));
-  avl = gpr_avl_add(avl, box(480), box(1560));
+  avl = gpr_avl_add(avl, box(93), box(1558), NULL);
+  avl = gpr_avl_add(avl, box(628), box(1559), NULL);
+  avl = gpr_avl_add(avl, box(480), box(1560), NULL);
   avl = remove_int(avl, 958);
   avl = remove_int(avl, 565);
   avl = remove_int(avl, 32);
   avl = remove_int(avl, 1);
   avl = remove_int(avl, 335);
-  avl = gpr_avl_add(avl, box(136), box(1566));
-  avl = gpr_avl_add(avl, box(469), box(1567));
+  avl = gpr_avl_add(avl, box(136), box(1566), NULL);
+  avl = gpr_avl_add(avl, box(469), box(1567), NULL);
   avl = remove_int(avl, 349);
-  avl = gpr_avl_add(avl, box(768), box(1569));
-  avl = gpr_avl_add(avl, box(915), box(1570));
+  avl = gpr_avl_add(avl, box(768), box(1569), NULL);
+  avl = gpr_avl_add(avl, box(915), box(1570), NULL);
   avl = remove_int(avl, 1014);
-  avl = gpr_avl_add(avl, box(117), box(1572));
+  avl = gpr_avl_add(avl, box(117), box(1572), NULL);
   avl = remove_int(avl, 62);
-  avl = gpr_avl_add(avl, box(382), box(1574));
+  avl = gpr_avl_add(avl, box(382), box(1574), NULL);
   avl = remove_int(avl, 571);
-  avl = gpr_avl_add(avl, box(655), box(1576));
-  avl = gpr_avl_add(avl, box(323), box(1577));
+  avl = gpr_avl_add(avl, box(655), box(1576), NULL);
+  avl = gpr_avl_add(avl, box(323), box(1577), NULL);
   avl = remove_int(avl, 869);
   avl = remove_int(avl, 151);
-  avl = gpr_avl_add(avl, box(1019), box(1580));
-  avl = gpr_avl_add(avl, box(984), box(1581));
-  avl = gpr_avl_add(avl, box(870), box(1582));
-  avl = gpr_avl_add(avl, box(376), box(1583));
+  avl = gpr_avl_add(avl, box(1019), box(1580), NULL);
+  avl = gpr_avl_add(avl, box(984), box(1581), NULL);
+  avl = gpr_avl_add(avl, box(870), box(1582), NULL);
+  avl = gpr_avl_add(avl, box(376), box(1583), NULL);
   avl = remove_int(avl, 625);
-  avl = gpr_avl_add(avl, box(733), box(1585));
+  avl = gpr_avl_add(avl, box(733), box(1585), NULL);
   avl = remove_int(avl, 532);
   avl = remove_int(avl, 444);
-  avl = gpr_avl_add(avl, box(428), box(1588));
-  avl = gpr_avl_add(avl, box(860), box(1589));
-  avl = gpr_avl_add(avl, box(173), box(1590));
+  avl = gpr_avl_add(avl, box(428), box(1588), NULL);
+  avl = gpr_avl_add(avl, box(860), box(1589), NULL);
+  avl = gpr_avl_add(avl, box(173), box(1590), NULL);
   avl = remove_int(avl, 649);
   avl = remove_int(avl, 913);
   avl = remove_int(avl, 1);
   avl = remove_int(avl, 304);
-  avl = gpr_avl_add(avl, box(604), box(1595));
-  avl = gpr_avl_add(avl, box(639), box(1596));
+  avl = gpr_avl_add(avl, box(604), box(1595), NULL);
+  avl = gpr_avl_add(avl, box(639), box(1596), NULL);
   avl = remove_int(avl, 431);
-  avl = gpr_avl_add(avl, box(993), box(1598));
+  avl = gpr_avl_add(avl, box(993), box(1598), NULL);
   avl = remove_int(avl, 681);
   avl = remove_int(avl, 927);
-  avl = gpr_avl_add(avl, box(87), box(1601));
-  avl = gpr_avl_add(avl, box(91), box(1602));
+  avl = gpr_avl_add(avl, box(87), box(1601), NULL);
+  avl = gpr_avl_add(avl, box(91), box(1602), NULL);
   avl = remove_int(avl, 61);
   avl = remove_int(avl, 14);
   avl = remove_int(avl, 305);
   avl = remove_int(avl, 304);
   avl = remove_int(avl, 1016);
-  avl = gpr_avl_add(avl, box(903), box(1608));
-  avl = gpr_avl_add(avl, box(951), box(1609));
-  avl = gpr_avl_add(avl, box(146), box(1610));
-  avl = gpr_avl_add(avl, box(482), box(1611));
-  avl = gpr_avl_add(avl, box(71), box(1612));
+  avl = gpr_avl_add(avl, box(903), box(1608), NULL);
+  avl = gpr_avl_add(avl, box(951), box(1609), NULL);
+  avl = gpr_avl_add(avl, box(146), box(1610), NULL);
+  avl = gpr_avl_add(avl, box(482), box(1611), NULL);
+  avl = gpr_avl_add(avl, box(71), box(1612), NULL);
   avl = remove_int(avl, 246);
   avl = remove_int(avl, 696);
-  avl = gpr_avl_add(avl, box(636), box(1615));
-  avl = gpr_avl_add(avl, box(295), box(1616));
+  avl = gpr_avl_add(avl, box(636), box(1615), NULL);
+  avl = gpr_avl_add(avl, box(295), box(1616), NULL);
   avl = remove_int(avl, 11);
   avl = remove_int(avl, 231);
-  avl = gpr_avl_add(avl, box(905), box(1619));
-  avl = gpr_avl_add(avl, box(993), box(1620));
-  avl = gpr_avl_add(avl, box(433), box(1621));
-  avl = gpr_avl_add(avl, box(117), box(1622));
-  avl = gpr_avl_add(avl, box(467), box(1623));
+  avl = gpr_avl_add(avl, box(905), box(1619), NULL);
+  avl = gpr_avl_add(avl, box(993), box(1620), NULL);
+  avl = gpr_avl_add(avl, box(433), box(1621), NULL);
+  avl = gpr_avl_add(avl, box(117), box(1622), NULL);
+  avl = gpr_avl_add(avl, box(467), box(1623), NULL);
   avl = remove_int(avl, 419);
-  avl = gpr_avl_add(avl, box(179), box(1625));
+  avl = gpr_avl_add(avl, box(179), box(1625), NULL);
   avl = remove_int(avl, 926);
   avl = remove_int(avl, 326);
-  avl = gpr_avl_add(avl, box(551), box(1628));
+  avl = gpr_avl_add(avl, box(551), box(1628), NULL);
   avl = remove_int(avl, 14);
   avl = remove_int(avl, 476);
   avl = remove_int(avl, 823);
-  avl = gpr_avl_add(avl, box(350), box(1632));
-  avl = gpr_avl_add(avl, box(133), box(1633));
+  avl = gpr_avl_add(avl, box(350), box(1632), NULL);
+  avl = gpr_avl_add(avl, box(133), box(1633), NULL);
   avl = remove_int(avl, 906);
-  avl = gpr_avl_add(avl, box(827), box(1635));
-  avl = gpr_avl_add(avl, box(201), box(1636));
+  avl = gpr_avl_add(avl, box(827), box(1635), NULL);
+  avl = gpr_avl_add(avl, box(201), box(1636), NULL);
   avl = remove_int(avl, 124);
   avl = remove_int(avl, 662);
-  avl = gpr_avl_add(avl, box(314), box(1639));
-  avl = gpr_avl_add(avl, box(986), box(1640));
-  avl = gpr_avl_add(avl, box(622), box(1641));
+  avl = gpr_avl_add(avl, box(314), box(1639), NULL);
+  avl = gpr_avl_add(avl, box(986), box(1640), NULL);
+  avl = gpr_avl_add(avl, box(622), box(1641), NULL);
   avl = remove_int(avl, 130);
-  avl = gpr_avl_add(avl, box(861), box(1643));
+  avl = gpr_avl_add(avl, box(861), box(1643), NULL);
   avl = remove_int(avl, 497);
   avl = remove_int(avl, 905);
-  avl = gpr_avl_add(avl, box(502), box(1646));
+  avl = gpr_avl_add(avl, box(502), box(1646), NULL);
   avl = remove_int(avl, 721);
-  avl = gpr_avl_add(avl, box(514), box(1648));
-  avl = gpr_avl_add(avl, box(410), box(1649));
+  avl = gpr_avl_add(avl, box(514), box(1648), NULL);
+  avl = gpr_avl_add(avl, box(410), box(1649), NULL);
   avl = remove_int(avl, 869);
   avl = remove_int(avl, 247);
-  avl = gpr_avl_add(avl, box(450), box(1652));
+  avl = gpr_avl_add(avl, box(450), box(1652), NULL);
   avl = remove_int(avl, 364);
-  avl = gpr_avl_add(avl, box(963), box(1654));
-  avl = gpr_avl_add(avl, box(146), box(1655));
+  avl = gpr_avl_add(avl, box(963), box(1654), NULL);
+  avl = gpr_avl_add(avl, box(146), box(1655), NULL);
   avl = remove_int(avl, 147);
   avl = remove_int(avl, 789);
-  avl = gpr_avl_add(avl, box(693), box(1658));
-  avl = gpr_avl_add(avl, box(959), box(1659));
+  avl = gpr_avl_add(avl, box(693), box(1658), NULL);
+  avl = gpr_avl_add(avl, box(959), box(1659), NULL);
   avl = remove_int(avl, 478);
-  avl = gpr_avl_add(avl, box(116), box(1661));
-  avl = gpr_avl_add(avl, box(520), box(1662));
-  avl = gpr_avl_add(avl, box(809), box(1663));
-  avl = gpr_avl_add(avl, box(667), box(1664));
-  avl = gpr_avl_add(avl, box(406), box(1665));
+  avl = gpr_avl_add(avl, box(116), box(1661), NULL);
+  avl = gpr_avl_add(avl, box(520), box(1662), NULL);
+  avl = gpr_avl_add(avl, box(809), box(1663), NULL);
+  avl = gpr_avl_add(avl, box(667), box(1664), NULL);
+  avl = gpr_avl_add(avl, box(406), box(1665), NULL);
   avl = remove_int(avl, 409);
-  avl = gpr_avl_add(avl, box(558), box(1667));
-  avl = gpr_avl_add(avl, box(0), box(1668));
-  avl = gpr_avl_add(avl, box(948), box(1669));
-  avl = gpr_avl_add(avl, box(576), box(1670));
+  avl = gpr_avl_add(avl, box(558), box(1667), NULL);
+  avl = gpr_avl_add(avl, box(0), box(1668), NULL);
+  avl = gpr_avl_add(avl, box(948), box(1669), NULL);
+  avl = gpr_avl_add(avl, box(576), box(1670), NULL);
   avl = remove_int(avl, 864);
   avl = remove_int(avl, 840);
   avl = remove_int(avl, 1001);
-  avl = gpr_avl_add(avl, box(232), box(1674));
+  avl = gpr_avl_add(avl, box(232), box(1674), NULL);
   avl = remove_int(avl, 676);
   avl = remove_int(avl, 752);
   avl = remove_int(avl, 667);
   avl = remove_int(avl, 605);
-  avl = gpr_avl_add(avl, box(258), box(1679));
-  avl = gpr_avl_add(avl, box(648), box(1680));
-  avl = gpr_avl_add(avl, box(761), box(1681));
+  avl = gpr_avl_add(avl, box(258), box(1679), NULL);
+  avl = gpr_avl_add(avl, box(648), box(1680), NULL);
+  avl = gpr_avl_add(avl, box(761), box(1681), NULL);
   avl = remove_int(avl, 293);
   avl = remove_int(avl, 893);
-  avl = gpr_avl_add(avl, box(194), box(1684));
+  avl = gpr_avl_add(avl, box(194), box(1684), NULL);
   avl = remove_int(avl, 233);
-  avl = gpr_avl_add(avl, box(888), box(1686));
+  avl = gpr_avl_add(avl, box(888), box(1686), NULL);
   avl = remove_int(avl, 470);
   avl = remove_int(avl, 703);
   avl = remove_int(avl, 190);
   avl = remove_int(avl, 359);
-  avl = gpr_avl_add(avl, box(621), box(1691));
+  avl = gpr_avl_add(avl, box(621), box(1691), NULL);
   avl = remove_int(avl, 634);
   avl = remove_int(avl, 335);
-  avl = gpr_avl_add(avl, box(718), box(1694));
-  avl = gpr_avl_add(avl, box(463), box(1695));
-  avl = gpr_avl_add(avl, box(233), box(1696));
+  avl = gpr_avl_add(avl, box(718), box(1694), NULL);
+  avl = gpr_avl_add(avl, box(463), box(1695), NULL);
+  avl = gpr_avl_add(avl, box(233), box(1696), NULL);
   avl = remove_int(avl, 376);
   avl = remove_int(avl, 496);
   avl = remove_int(avl, 819);
   avl = remove_int(avl, 38);
   avl = remove_int(avl, 436);
   avl = remove_int(avl, 102);
-  avl = gpr_avl_add(avl, box(607), box(1703));
+  avl = gpr_avl_add(avl, box(607), box(1703), NULL);
   avl = remove_int(avl, 329);
-  avl = gpr_avl_add(avl, box(716), box(1705));
+  avl = gpr_avl_add(avl, box(716), box(1705), NULL);
   avl = remove_int(avl, 639);
   avl = remove_int(avl, 775);
   avl = remove_int(avl, 578);
@@ -2849,402 +2851,402 @@
   avl = remove_int(avl, 679);
   avl = remove_int(avl, 615);
   avl = remove_int(avl, 104);
-  avl = gpr_avl_add(avl, box(414), box(1713));
-  avl = gpr_avl_add(avl, box(212), box(1714));
-  avl = gpr_avl_add(avl, box(266), box(1715));
-  avl = gpr_avl_add(avl, box(238), box(1716));
+  avl = gpr_avl_add(avl, box(414), box(1713), NULL);
+  avl = gpr_avl_add(avl, box(212), box(1714), NULL);
+  avl = gpr_avl_add(avl, box(266), box(1715), NULL);
+  avl = gpr_avl_add(avl, box(238), box(1716), NULL);
   avl = remove_int(avl, 153);
-  avl = gpr_avl_add(avl, box(585), box(1718));
+  avl = gpr_avl_add(avl, box(585), box(1718), NULL);
   avl = remove_int(avl, 121);
-  avl = gpr_avl_add(avl, box(534), box(1720));
+  avl = gpr_avl_add(avl, box(534), box(1720), NULL);
   avl = remove_int(avl, 579);
-  avl = gpr_avl_add(avl, box(127), box(1722));
-  avl = gpr_avl_add(avl, box(399), box(1723));
+  avl = gpr_avl_add(avl, box(127), box(1722), NULL);
+  avl = gpr_avl_add(avl, box(399), box(1723), NULL);
   avl = remove_int(avl, 417);
-  avl = gpr_avl_add(avl, box(978), box(1725));
-  avl = gpr_avl_add(avl, box(768), box(1726));
+  avl = gpr_avl_add(avl, box(978), box(1725), NULL);
+  avl = gpr_avl_add(avl, box(768), box(1726), NULL);
   avl = remove_int(avl, 985);
-  avl = gpr_avl_add(avl, box(536), box(1728));
-  avl = gpr_avl_add(avl, box(449), box(1729));
-  avl = gpr_avl_add(avl, box(586), box(1730));
+  avl = gpr_avl_add(avl, box(536), box(1728), NULL);
+  avl = gpr_avl_add(avl, box(449), box(1729), NULL);
+  avl = gpr_avl_add(avl, box(586), box(1730), NULL);
   avl = remove_int(avl, 998);
   avl = remove_int(avl, 394);
   avl = remove_int(avl, 141);
-  avl = gpr_avl_add(avl, box(889), box(1734));
-  avl = gpr_avl_add(avl, box(871), box(1735));
-  avl = gpr_avl_add(avl, box(76), box(1736));
-  avl = gpr_avl_add(avl, box(549), box(1737));
-  avl = gpr_avl_add(avl, box(757), box(1738));
+  avl = gpr_avl_add(avl, box(889), box(1734), NULL);
+  avl = gpr_avl_add(avl, box(871), box(1735), NULL);
+  avl = gpr_avl_add(avl, box(76), box(1736), NULL);
+  avl = gpr_avl_add(avl, box(549), box(1737), NULL);
+  avl = gpr_avl_add(avl, box(757), box(1738), NULL);
   avl = remove_int(avl, 908);
-  avl = gpr_avl_add(avl, box(789), box(1740));
+  avl = gpr_avl_add(avl, box(789), box(1740), NULL);
   avl = remove_int(avl, 224);
-  avl = gpr_avl_add(avl, box(407), box(1742));
-  avl = gpr_avl_add(avl, box(381), box(1743));
-  avl = gpr_avl_add(avl, box(561), box(1744));
-  avl = gpr_avl_add(avl, box(667), box(1745));
-  avl = gpr_avl_add(avl, box(522), box(1746));
-  avl = gpr_avl_add(avl, box(948), box(1747));
+  avl = gpr_avl_add(avl, box(407), box(1742), NULL);
+  avl = gpr_avl_add(avl, box(381), box(1743), NULL);
+  avl = gpr_avl_add(avl, box(561), box(1744), NULL);
+  avl = gpr_avl_add(avl, box(667), box(1745), NULL);
+  avl = gpr_avl_add(avl, box(522), box(1746), NULL);
+  avl = gpr_avl_add(avl, box(948), box(1747), NULL);
   avl = remove_int(avl, 770);
-  avl = gpr_avl_add(avl, box(872), box(1749));
-  avl = gpr_avl_add(avl, box(327), box(1750));
+  avl = gpr_avl_add(avl, box(872), box(1749), NULL);
+  avl = gpr_avl_add(avl, box(327), box(1750), NULL);
   avl = remove_int(avl, 10);
-  avl = gpr_avl_add(avl, box(122), box(1752));
+  avl = gpr_avl_add(avl, box(122), box(1752), NULL);
   avl = remove_int(avl, 606);
-  avl = gpr_avl_add(avl, box(485), box(1754));
+  avl = gpr_avl_add(avl, box(485), box(1754), NULL);
   avl = remove_int(avl, 6);
-  avl = gpr_avl_add(avl, box(329), box(1756));
-  avl = gpr_avl_add(avl, box(783), box(1757));
+  avl = gpr_avl_add(avl, box(329), box(1756), NULL);
+  avl = gpr_avl_add(avl, box(783), box(1757), NULL);
   avl = remove_int(avl, 416);
-  avl = gpr_avl_add(avl, box(656), box(1759));
-  avl = gpr_avl_add(avl, box(971), box(1760));
-  avl = gpr_avl_add(avl, box(77), box(1761));
-  avl = gpr_avl_add(avl, box(942), box(1762));
+  avl = gpr_avl_add(avl, box(656), box(1759), NULL);
+  avl = gpr_avl_add(avl, box(971), box(1760), NULL);
+  avl = gpr_avl_add(avl, box(77), box(1761), NULL);
+  avl = gpr_avl_add(avl, box(942), box(1762), NULL);
   avl = remove_int(avl, 361);
-  avl = gpr_avl_add(avl, box(66), box(1764));
-  avl = gpr_avl_add(avl, box(299), box(1765));
-  avl = gpr_avl_add(avl, box(929), box(1766));
-  avl = gpr_avl_add(avl, box(797), box(1767));
+  avl = gpr_avl_add(avl, box(66), box(1764), NULL);
+  avl = gpr_avl_add(avl, box(299), box(1765), NULL);
+  avl = gpr_avl_add(avl, box(929), box(1766), NULL);
+  avl = gpr_avl_add(avl, box(797), box(1767), NULL);
   avl = remove_int(avl, 869);
   avl = remove_int(avl, 907);
-  avl = gpr_avl_add(avl, box(870), box(1770));
+  avl = gpr_avl_add(avl, box(870), box(1770), NULL);
   avl = remove_int(avl, 580);
   avl = remove_int(avl, 120);
-  avl = gpr_avl_add(avl, box(913), box(1773));
+  avl = gpr_avl_add(avl, box(913), box(1773), NULL);
   avl = remove_int(avl, 480);
-  avl = gpr_avl_add(avl, box(489), box(1775));
+  avl = gpr_avl_add(avl, box(489), box(1775), NULL);
   avl = remove_int(avl, 845);
-  avl = gpr_avl_add(avl, box(896), box(1777));
+  avl = gpr_avl_add(avl, box(896), box(1777), NULL);
   avl = remove_int(avl, 567);
   avl = remove_int(avl, 427);
-  avl = gpr_avl_add(avl, box(443), box(1780));
-  avl = gpr_avl_add(avl, box(3), box(1781));
+  avl = gpr_avl_add(avl, box(443), box(1780), NULL);
+  avl = gpr_avl_add(avl, box(3), box(1781), NULL);
   avl = remove_int(avl, 12);
-  avl = gpr_avl_add(avl, box(376), box(1783));
-  avl = gpr_avl_add(avl, box(155), box(1784));
-  avl = gpr_avl_add(avl, box(188), box(1785));
-  avl = gpr_avl_add(avl, box(149), box(1786));
-  avl = gpr_avl_add(avl, box(178), box(1787));
+  avl = gpr_avl_add(avl, box(376), box(1783), NULL);
+  avl = gpr_avl_add(avl, box(155), box(1784), NULL);
+  avl = gpr_avl_add(avl, box(188), box(1785), NULL);
+  avl = gpr_avl_add(avl, box(149), box(1786), NULL);
+  avl = gpr_avl_add(avl, box(178), box(1787), NULL);
   avl = remove_int(avl, 84);
-  avl = gpr_avl_add(avl, box(805), box(1789));
-  avl = gpr_avl_add(avl, box(612), box(1790));
+  avl = gpr_avl_add(avl, box(805), box(1789), NULL);
+  avl = gpr_avl_add(avl, box(612), box(1790), NULL);
   avl = remove_int(avl, 991);
-  avl = gpr_avl_add(avl, box(837), box(1792));
+  avl = gpr_avl_add(avl, box(837), box(1792), NULL);
   avl = remove_int(avl, 173);
   avl = remove_int(avl, 72);
-  avl = gpr_avl_add(avl, box(1014), box(1795));
+  avl = gpr_avl_add(avl, box(1014), box(1795), NULL);
   avl = remove_int(avl, 303);
-  avl = gpr_avl_add(avl, box(865), box(1797));
-  avl = gpr_avl_add(avl, box(793), box(1798));
+  avl = gpr_avl_add(avl, box(865), box(1797), NULL);
+  avl = gpr_avl_add(avl, box(793), box(1798), NULL);
   avl = remove_int(avl, 173);
   avl = remove_int(avl, 477);
-  avl = gpr_avl_add(avl, box(950), box(1801));
-  avl = gpr_avl_add(avl, box(105), box(1802));
-  avl = gpr_avl_add(avl, box(895), box(1803));
-  avl = gpr_avl_add(avl, box(171), box(1804));
-  avl = gpr_avl_add(avl, box(753), box(1805));
-  avl = gpr_avl_add(avl, box(946), box(1806));
+  avl = gpr_avl_add(avl, box(950), box(1801), NULL);
+  avl = gpr_avl_add(avl, box(105), box(1802), NULL);
+  avl = gpr_avl_add(avl, box(895), box(1803), NULL);
+  avl = gpr_avl_add(avl, box(171), box(1804), NULL);
+  avl = gpr_avl_add(avl, box(753), box(1805), NULL);
+  avl = gpr_avl_add(avl, box(946), box(1806), NULL);
   avl = remove_int(avl, 194);
   avl = remove_int(avl, 559);
   avl = remove_int(avl, 116);
-  avl = gpr_avl_add(avl, box(968), box(1810));
+  avl = gpr_avl_add(avl, box(968), box(1810), NULL);
   avl = remove_int(avl, 124);
   avl = remove_int(avl, 99);
-  avl = gpr_avl_add(avl, box(563), box(1813));
+  avl = gpr_avl_add(avl, box(563), box(1813), NULL);
   avl = remove_int(avl, 182);
-  avl = gpr_avl_add(avl, box(816), box(1815));
+  avl = gpr_avl_add(avl, box(816), box(1815), NULL);
   avl = remove_int(avl, 73);
   avl = remove_int(avl, 261);
-  avl = gpr_avl_add(avl, box(847), box(1818));
-  avl = gpr_avl_add(avl, box(368), box(1819));
-  avl = gpr_avl_add(avl, box(808), box(1820));
-  avl = gpr_avl_add(avl, box(779), box(1821));
+  avl = gpr_avl_add(avl, box(847), box(1818), NULL);
+  avl = gpr_avl_add(avl, box(368), box(1819), NULL);
+  avl = gpr_avl_add(avl, box(808), box(1820), NULL);
+  avl = gpr_avl_add(avl, box(779), box(1821), NULL);
   avl = remove_int(avl, 818);
-  avl = gpr_avl_add(avl, box(466), box(1823));
+  avl = gpr_avl_add(avl, box(466), box(1823), NULL);
   avl = remove_int(avl, 316);
-  avl = gpr_avl_add(avl, box(986), box(1825));
-  avl = gpr_avl_add(avl, box(688), box(1826));
-  avl = gpr_avl_add(avl, box(509), box(1827));
-  avl = gpr_avl_add(avl, box(51), box(1828));
+  avl = gpr_avl_add(avl, box(986), box(1825), NULL);
+  avl = gpr_avl_add(avl, box(688), box(1826), NULL);
+  avl = gpr_avl_add(avl, box(509), box(1827), NULL);
+  avl = gpr_avl_add(avl, box(51), box(1828), NULL);
   avl = remove_int(avl, 655);
   avl = remove_int(avl, 785);
   avl = remove_int(avl, 893);
-  avl = gpr_avl_add(avl, box(167), box(1832));
+  avl = gpr_avl_add(avl, box(167), box(1832), NULL);
   avl = remove_int(avl, 13);
   avl = remove_int(avl, 263);
-  avl = gpr_avl_add(avl, box(1009), box(1835));
+  avl = gpr_avl_add(avl, box(1009), box(1835), NULL);
   avl = remove_int(avl, 480);
   avl = remove_int(avl, 778);
   avl = remove_int(avl, 713);
   avl = remove_int(avl, 628);
-  avl = gpr_avl_add(avl, box(803), box(1840));
+  avl = gpr_avl_add(avl, box(803), box(1840), NULL);
   avl = remove_int(avl, 267);
-  avl = gpr_avl_add(avl, box(676), box(1842));
-  avl = gpr_avl_add(avl, box(231), box(1843));
-  avl = gpr_avl_add(avl, box(824), box(1844));
+  avl = gpr_avl_add(avl, box(676), box(1842), NULL);
+  avl = gpr_avl_add(avl, box(231), box(1843), NULL);
+  avl = gpr_avl_add(avl, box(824), box(1844), NULL);
   avl = remove_int(avl, 961);
-  avl = gpr_avl_add(avl, box(311), box(1846));
-  avl = gpr_avl_add(avl, box(420), box(1847));
-  avl = gpr_avl_add(avl, box(960), box(1848));
-  avl = gpr_avl_add(avl, box(468), box(1849));
-  avl = gpr_avl_add(avl, box(815), box(1850));
+  avl = gpr_avl_add(avl, box(311), box(1846), NULL);
+  avl = gpr_avl_add(avl, box(420), box(1847), NULL);
+  avl = gpr_avl_add(avl, box(960), box(1848), NULL);
+  avl = gpr_avl_add(avl, box(468), box(1849), NULL);
+  avl = gpr_avl_add(avl, box(815), box(1850), NULL);
   avl = remove_int(avl, 247);
   avl = remove_int(avl, 194);
-  avl = gpr_avl_add(avl, box(546), box(1853));
+  avl = gpr_avl_add(avl, box(546), box(1853), NULL);
   avl = remove_int(avl, 222);
   avl = remove_int(avl, 914);
   avl = remove_int(avl, 741);
-  avl = gpr_avl_add(avl, box(470), box(1857));
-  avl = gpr_avl_add(avl, box(933), box(1858));
-  avl = gpr_avl_add(avl, box(97), box(1859));
+  avl = gpr_avl_add(avl, box(470), box(1857), NULL);
+  avl = gpr_avl_add(avl, box(933), box(1858), NULL);
+  avl = gpr_avl_add(avl, box(97), box(1859), NULL);
   avl = remove_int(avl, 564);
   avl = remove_int(avl, 295);
-  avl = gpr_avl_add(avl, box(864), box(1862));
+  avl = gpr_avl_add(avl, box(864), box(1862), NULL);
   avl = remove_int(avl, 329);
-  avl = gpr_avl_add(avl, box(124), box(1864));
-  avl = gpr_avl_add(avl, box(1000), box(1865));
-  avl = gpr_avl_add(avl, box(228), box(1866));
-  avl = gpr_avl_add(avl, box(187), box(1867));
+  avl = gpr_avl_add(avl, box(124), box(1864), NULL);
+  avl = gpr_avl_add(avl, box(1000), box(1865), NULL);
+  avl = gpr_avl_add(avl, box(228), box(1866), NULL);
+  avl = gpr_avl_add(avl, box(187), box(1867), NULL);
   avl = remove_int(avl, 224);
   avl = remove_int(avl, 306);
   avl = remove_int(avl, 884);
-  avl = gpr_avl_add(avl, box(449), box(1871));
-  avl = gpr_avl_add(avl, box(353), box(1872));
-  avl = gpr_avl_add(avl, box(994), box(1873));
-  avl = gpr_avl_add(avl, box(596), box(1874));
-  avl = gpr_avl_add(avl, box(996), box(1875));
-  avl = gpr_avl_add(avl, box(101), box(1876));
-  avl = gpr_avl_add(avl, box(1012), box(1877));
-  avl = gpr_avl_add(avl, box(982), box(1878));
-  avl = gpr_avl_add(avl, box(742), box(1879));
+  avl = gpr_avl_add(avl, box(449), box(1871), NULL);
+  avl = gpr_avl_add(avl, box(353), box(1872), NULL);
+  avl = gpr_avl_add(avl, box(994), box(1873), NULL);
+  avl = gpr_avl_add(avl, box(596), box(1874), NULL);
+  avl = gpr_avl_add(avl, box(996), box(1875), NULL);
+  avl = gpr_avl_add(avl, box(101), box(1876), NULL);
+  avl = gpr_avl_add(avl, box(1012), box(1877), NULL);
+  avl = gpr_avl_add(avl, box(982), box(1878), NULL);
+  avl = gpr_avl_add(avl, box(742), box(1879), NULL);
   avl = remove_int(avl, 92);
   avl = remove_int(avl, 1022);
-  avl = gpr_avl_add(avl, box(941), box(1882));
+  avl = gpr_avl_add(avl, box(941), box(1882), NULL);
   avl = remove_int(avl, 742);
   avl = remove_int(avl, 919);
-  avl = gpr_avl_add(avl, box(588), box(1885));
+  avl = gpr_avl_add(avl, box(588), box(1885), NULL);
   avl = remove_int(avl, 221);
-  avl = gpr_avl_add(avl, box(356), box(1887));
-  avl = gpr_avl_add(avl, box(932), box(1888));
+  avl = gpr_avl_add(avl, box(356), box(1887), NULL);
+  avl = gpr_avl_add(avl, box(932), box(1888), NULL);
   avl = remove_int(avl, 837);
-  avl = gpr_avl_add(avl, box(394), box(1890));
-  avl = gpr_avl_add(avl, box(642), box(1891));
-  avl = gpr_avl_add(avl, box(52), box(1892));
-  avl = gpr_avl_add(avl, box(437), box(1893));
-  avl = gpr_avl_add(avl, box(948), box(1894));
-  avl = gpr_avl_add(avl, box(93), box(1895));
+  avl = gpr_avl_add(avl, box(394), box(1890), NULL);
+  avl = gpr_avl_add(avl, box(642), box(1891), NULL);
+  avl = gpr_avl_add(avl, box(52), box(1892), NULL);
+  avl = gpr_avl_add(avl, box(437), box(1893), NULL);
+  avl = gpr_avl_add(avl, box(948), box(1894), NULL);
+  avl = gpr_avl_add(avl, box(93), box(1895), NULL);
   avl = remove_int(avl, 873);
   avl = remove_int(avl, 336);
   avl = remove_int(avl, 277);
   avl = remove_int(avl, 932);
-  avl = gpr_avl_add(avl, box(80), box(1900));
-  avl = gpr_avl_add(avl, box(952), box(1901));
-  avl = gpr_avl_add(avl, box(510), box(1902));
+  avl = gpr_avl_add(avl, box(80), box(1900), NULL);
+  avl = gpr_avl_add(avl, box(952), box(1901), NULL);
+  avl = gpr_avl_add(avl, box(510), box(1902), NULL);
   avl = remove_int(avl, 876);
   avl = remove_int(avl, 612);
-  avl = gpr_avl_add(avl, box(923), box(1905));
-  avl = gpr_avl_add(avl, box(475), box(1906));
+  avl = gpr_avl_add(avl, box(923), box(1905), NULL);
+  avl = gpr_avl_add(avl, box(475), box(1906), NULL);
   avl = remove_int(avl, 478);
   avl = remove_int(avl, 148);
-  avl = gpr_avl_add(avl, box(538), box(1909));
+  avl = gpr_avl_add(avl, box(538), box(1909), NULL);
   avl = remove_int(avl, 47);
-  avl = gpr_avl_add(avl, box(89), box(1911));
+  avl = gpr_avl_add(avl, box(89), box(1911), NULL);
   avl = remove_int(avl, 723);
-  avl = gpr_avl_add(avl, box(687), box(1913));
-  avl = gpr_avl_add(avl, box(480), box(1914));
-  avl = gpr_avl_add(avl, box(149), box(1915));
+  avl = gpr_avl_add(avl, box(687), box(1913), NULL);
+  avl = gpr_avl_add(avl, box(480), box(1914), NULL);
+  avl = gpr_avl_add(avl, box(149), box(1915), NULL);
   avl = remove_int(avl, 68);
   avl = remove_int(avl, 862);
   avl = remove_int(avl, 363);
-  avl = gpr_avl_add(avl, box(996), box(1919));
+  avl = gpr_avl_add(avl, box(996), box(1919), NULL);
   avl = remove_int(avl, 380);
-  avl = gpr_avl_add(avl, box(957), box(1921));
+  avl = gpr_avl_add(avl, box(957), box(1921), NULL);
   avl = remove_int(avl, 413);
-  avl = gpr_avl_add(avl, box(360), box(1923));
-  avl = gpr_avl_add(avl, box(304), box(1924));
-  avl = gpr_avl_add(avl, box(634), box(1925));
-  avl = gpr_avl_add(avl, box(506), box(1926));
+  avl = gpr_avl_add(avl, box(360), box(1923), NULL);
+  avl = gpr_avl_add(avl, box(304), box(1924), NULL);
+  avl = gpr_avl_add(avl, box(634), box(1925), NULL);
+  avl = gpr_avl_add(avl, box(506), box(1926), NULL);
   avl = remove_int(avl, 248);
-  avl = gpr_avl_add(avl, box(124), box(1928));
-  avl = gpr_avl_add(avl, box(181), box(1929));
+  avl = gpr_avl_add(avl, box(124), box(1928), NULL);
+  avl = gpr_avl_add(avl, box(181), box(1929), NULL);
   avl = remove_int(avl, 507);
-  avl = gpr_avl_add(avl, box(141), box(1931));
+  avl = gpr_avl_add(avl, box(141), box(1931), NULL);
   avl = remove_int(avl, 409);
   avl = remove_int(avl, 129);
   avl = remove_int(avl, 694);
   avl = remove_int(avl, 723);
-  avl = gpr_avl_add(avl, box(998), box(1936));
-  avl = gpr_avl_add(avl, box(906), box(1937));
-  avl = gpr_avl_add(avl, box(44), box(1938));
+  avl = gpr_avl_add(avl, box(998), box(1936), NULL);
+  avl = gpr_avl_add(avl, box(906), box(1937), NULL);
+  avl = gpr_avl_add(avl, box(44), box(1938), NULL);
   avl = remove_int(avl, 949);
   avl = remove_int(avl, 117);
-  avl = gpr_avl_add(avl, box(700), box(1941));
-  avl = gpr_avl_add(avl, box(258), box(1942));
+  avl = gpr_avl_add(avl, box(700), box(1941), NULL);
+  avl = gpr_avl_add(avl, box(258), box(1942), NULL);
   avl = remove_int(avl, 828);
-  avl = gpr_avl_add(avl, box(860), box(1944));
-  avl = gpr_avl_add(avl, box(987), box(1945));
-  avl = gpr_avl_add(avl, box(316), box(1946));
-  avl = gpr_avl_add(avl, box(919), box(1947));
+  avl = gpr_avl_add(avl, box(860), box(1944), NULL);
+  avl = gpr_avl_add(avl, box(987), box(1945), NULL);
+  avl = gpr_avl_add(avl, box(316), box(1946), NULL);
+  avl = gpr_avl_add(avl, box(919), box(1947), NULL);
   avl = remove_int(avl, 84);
-  avl = gpr_avl_add(avl, box(473), box(1949));
+  avl = gpr_avl_add(avl, box(473), box(1949), NULL);
   avl = remove_int(avl, 127);
   avl = remove_int(avl, 829);
   avl = remove_int(avl, 829);
-  avl = gpr_avl_add(avl, box(488), box(1953));
-  avl = gpr_avl_add(avl, box(954), box(1954));
+  avl = gpr_avl_add(avl, box(488), box(1953), NULL);
+  avl = gpr_avl_add(avl, box(954), box(1954), NULL);
   avl = remove_int(avl, 198);
   avl = remove_int(avl, 972);
   avl = remove_int(avl, 670);
-  avl = gpr_avl_add(avl, box(822), box(1958));
+  avl = gpr_avl_add(avl, box(822), box(1958), NULL);
   avl = remove_int(avl, 589);
   avl = remove_int(avl, 459);
-  avl = gpr_avl_add(avl, box(1003), box(1961));
-  avl = gpr_avl_add(avl, box(657), box(1962));
-  avl = gpr_avl_add(avl, box(477), box(1963));
-  avl = gpr_avl_add(avl, box(923), box(1964));
+  avl = gpr_avl_add(avl, box(1003), box(1961), NULL);
+  avl = gpr_avl_add(avl, box(657), box(1962), NULL);
+  avl = gpr_avl_add(avl, box(477), box(1963), NULL);
+  avl = gpr_avl_add(avl, box(923), box(1964), NULL);
   avl = remove_int(avl, 496);
   avl = remove_int(avl, 99);
-  avl = gpr_avl_add(avl, box(127), box(1967));
-  avl = gpr_avl_add(avl, box(1013), box(1968));
-  avl = gpr_avl_add(avl, box(778), box(1969));
+  avl = gpr_avl_add(avl, box(127), box(1967), NULL);
+  avl = gpr_avl_add(avl, box(1013), box(1968), NULL);
+  avl = gpr_avl_add(avl, box(778), box(1969), NULL);
   avl = remove_int(avl, 5);
   avl = remove_int(avl, 990);
   avl = remove_int(avl, 850);
   avl = remove_int(avl, 160);
   avl = remove_int(avl, 86);
-  avl = gpr_avl_add(avl, box(283), box(1975));
+  avl = gpr_avl_add(avl, box(283), box(1975), NULL);
   avl = remove_int(avl, 278);
   avl = remove_int(avl, 297);
   avl = remove_int(avl, 137);
   avl = remove_int(avl, 653);
-  avl = gpr_avl_add(avl, box(702), box(1980));
+  avl = gpr_avl_add(avl, box(702), box(1980), NULL);
   avl = remove_int(avl, 63);
   avl = remove_int(avl, 427);
   avl = remove_int(avl, 706);
   avl = remove_int(avl, 806);
-  avl = gpr_avl_add(avl, box(335), box(1985));
-  avl = gpr_avl_add(avl, box(412), box(1986));
+  avl = gpr_avl_add(avl, box(335), box(1985), NULL);
+  avl = gpr_avl_add(avl, box(412), box(1986), NULL);
   avl = remove_int(avl, 766);
   avl = remove_int(avl, 937);
   avl = remove_int(avl, 886);
   avl = remove_int(avl, 652);
-  avl = gpr_avl_add(avl, box(545), box(1991));
-  avl = gpr_avl_add(avl, box(408), box(1992));
-  avl = gpr_avl_add(avl, box(841), box(1993));
+  avl = gpr_avl_add(avl, box(545), box(1991), NULL);
+  avl = gpr_avl_add(avl, box(408), box(1992), NULL);
+  avl = gpr_avl_add(avl, box(841), box(1993), NULL);
   avl = remove_int(avl, 593);
-  avl = gpr_avl_add(avl, box(582), box(1995));
-  avl = gpr_avl_add(avl, box(597), box(1996));
+  avl = gpr_avl_add(avl, box(582), box(1995), NULL);
+  avl = gpr_avl_add(avl, box(597), box(1996), NULL);
   avl = remove_int(avl, 49);
   avl = remove_int(avl, 835);
-  avl = gpr_avl_add(avl, box(417), box(1999));
-  avl = gpr_avl_add(avl, box(191), box(2000));
+  avl = gpr_avl_add(avl, box(417), box(1999), NULL);
+  avl = gpr_avl_add(avl, box(191), box(2000), NULL);
   avl = remove_int(avl, 406);
-  avl = gpr_avl_add(avl, box(30), box(2002));
+  avl = gpr_avl_add(avl, box(30), box(2002), NULL);
   avl = remove_int(avl, 841);
   avl = remove_int(avl, 50);
-  avl = gpr_avl_add(avl, box(967), box(2005));
-  avl = gpr_avl_add(avl, box(849), box(2006));
+  avl = gpr_avl_add(avl, box(967), box(2005), NULL);
+  avl = gpr_avl_add(avl, box(849), box(2006), NULL);
   avl = remove_int(avl, 608);
-  avl = gpr_avl_add(avl, box(306), box(2008));
+  avl = gpr_avl_add(avl, box(306), box(2008), NULL);
   avl = remove_int(avl, 779);
-  avl = gpr_avl_add(avl, box(897), box(2010));
-  avl = gpr_avl_add(avl, box(147), box(2011));
+  avl = gpr_avl_add(avl, box(897), box(2010), NULL);
+  avl = gpr_avl_add(avl, box(147), box(2011), NULL);
   avl = remove_int(avl, 982);
-  avl = gpr_avl_add(avl, box(470), box(2013));
+  avl = gpr_avl_add(avl, box(470), box(2013), NULL);
   avl = remove_int(avl, 951);
-  avl = gpr_avl_add(avl, box(388), box(2015));
+  avl = gpr_avl_add(avl, box(388), box(2015), NULL);
   avl = remove_int(avl, 616);
   avl = remove_int(avl, 721);
   avl = remove_int(avl, 942);
   avl = remove_int(avl, 589);
-  avl = gpr_avl_add(avl, box(218), box(2020));
+  avl = gpr_avl_add(avl, box(218), box(2020), NULL);
   avl = remove_int(avl, 671);
-  avl = gpr_avl_add(avl, box(1020), box(2022));
+  avl = gpr_avl_add(avl, box(1020), box(2022), NULL);
   avl = remove_int(avl, 277);
-  avl = gpr_avl_add(avl, box(681), box(2024));
-  avl = gpr_avl_add(avl, box(179), box(2025));
-  avl = gpr_avl_add(avl, box(370), box(2026));
-  avl = gpr_avl_add(avl, box(0), box(2027));
+  avl = gpr_avl_add(avl, box(681), box(2024), NULL);
+  avl = gpr_avl_add(avl, box(179), box(2025), NULL);
+  avl = gpr_avl_add(avl, box(370), box(2026), NULL);
+  avl = gpr_avl_add(avl, box(0), box(2027), NULL);
   avl = remove_int(avl, 523);
-  avl = gpr_avl_add(avl, box(99), box(2029));
-  avl = gpr_avl_add(avl, box(334), box(2030));
-  avl = gpr_avl_add(avl, box(569), box(2031));
-  avl = gpr_avl_add(avl, box(257), box(2032));
+  avl = gpr_avl_add(avl, box(99), box(2029), NULL);
+  avl = gpr_avl_add(avl, box(334), box(2030), NULL);
+  avl = gpr_avl_add(avl, box(569), box(2031), NULL);
+  avl = gpr_avl_add(avl, box(257), box(2032), NULL);
   avl = remove_int(avl, 572);
-  avl = gpr_avl_add(avl, box(805), box(2034));
-  avl = gpr_avl_add(avl, box(143), box(2035));
-  avl = gpr_avl_add(avl, box(670), box(2036));
+  avl = gpr_avl_add(avl, box(805), box(2034), NULL);
+  avl = gpr_avl_add(avl, box(143), box(2035), NULL);
+  avl = gpr_avl_add(avl, box(670), box(2036), NULL);
   avl = remove_int(avl, 42);
-  avl = gpr_avl_add(avl, box(46), box(2038));
+  avl = gpr_avl_add(avl, box(46), box(2038), NULL);
   avl = remove_int(avl, 970);
-  avl = gpr_avl_add(avl, box(353), box(2040));
+  avl = gpr_avl_add(avl, box(353), box(2040), NULL);
   avl = remove_int(avl, 258);
-  avl = gpr_avl_add(avl, box(451), box(2042));
-  avl = gpr_avl_add(avl, box(28), box(2043));
-  avl = gpr_avl_add(avl, box(729), box(2044));
-  avl = gpr_avl_add(avl, box(401), box(2045));
-  avl = gpr_avl_add(avl, box(614), box(2046));
+  avl = gpr_avl_add(avl, box(451), box(2042), NULL);
+  avl = gpr_avl_add(avl, box(28), box(2043), NULL);
+  avl = gpr_avl_add(avl, box(729), box(2044), NULL);
+  avl = gpr_avl_add(avl, box(401), box(2045), NULL);
+  avl = gpr_avl_add(avl, box(614), box(2046), NULL);
   avl = remove_int(avl, 990);
   avl = remove_int(avl, 212);
   avl = remove_int(avl, 22);
   avl = remove_int(avl, 677);
-  avl = gpr_avl_add(avl, box(1016), box(2051));
-  avl = gpr_avl_add(avl, box(980), box(2052));
-  avl = gpr_avl_add(avl, box(990), box(2053));
-  avl = gpr_avl_add(avl, box(355), box(2054));
+  avl = gpr_avl_add(avl, box(1016), box(2051), NULL);
+  avl = gpr_avl_add(avl, box(980), box(2052), NULL);
+  avl = gpr_avl_add(avl, box(990), box(2053), NULL);
+  avl = gpr_avl_add(avl, box(355), box(2054), NULL);
   avl = remove_int(avl, 730);
   avl = remove_int(avl, 37);
-  avl = gpr_avl_add(avl, box(407), box(2057));
-  avl = gpr_avl_add(avl, box(222), box(2058));
-  avl = gpr_avl_add(avl, box(439), box(2059));
-  avl = gpr_avl_add(avl, box(563), box(2060));
+  avl = gpr_avl_add(avl, box(407), box(2057), NULL);
+  avl = gpr_avl_add(avl, box(222), box(2058), NULL);
+  avl = gpr_avl_add(avl, box(439), box(2059), NULL);
+  avl = gpr_avl_add(avl, box(563), box(2060), NULL);
   avl = remove_int(avl, 992);
   avl = remove_int(avl, 786);
-  avl = gpr_avl_add(avl, box(1), box(2063));
-  avl = gpr_avl_add(avl, box(473), box(2064));
-  avl = gpr_avl_add(avl, box(992), box(2065));
+  avl = gpr_avl_add(avl, box(1), box(2063), NULL);
+  avl = gpr_avl_add(avl, box(473), box(2064), NULL);
+  avl = gpr_avl_add(avl, box(992), box(2065), NULL);
   avl = remove_int(avl, 190);
   avl = remove_int(avl, 450);
   avl = remove_int(avl, 1020);
   avl = remove_int(avl, 149);
-  avl = gpr_avl_add(avl, box(329), box(2070));
-  avl = gpr_avl_add(avl, box(35), box(2071));
+  avl = gpr_avl_add(avl, box(329), box(2070), NULL);
+  avl = gpr_avl_add(avl, box(35), box(2071), NULL);
   avl = remove_int(avl, 843);
-  avl = gpr_avl_add(avl, box(855), box(2073));
+  avl = gpr_avl_add(avl, box(855), box(2073), NULL);
   avl = remove_int(avl, 878);
-  avl = gpr_avl_add(avl, box(993), box(2075));
-  avl = gpr_avl_add(avl, box(87), box(2076));
-  avl = gpr_avl_add(avl, box(572), box(2077));
+  avl = gpr_avl_add(avl, box(993), box(2075), NULL);
+  avl = gpr_avl_add(avl, box(87), box(2076), NULL);
+  avl = gpr_avl_add(avl, box(572), box(2077), NULL);
   avl = remove_int(avl, 896);
-  avl = gpr_avl_add(avl, box(849), box(2079));
+  avl = gpr_avl_add(avl, box(849), box(2079), NULL);
   avl = remove_int(avl, 597);
-  avl = gpr_avl_add(avl, box(472), box(2081));
+  avl = gpr_avl_add(avl, box(472), box(2081), NULL);
   avl = remove_int(avl, 778);
   avl = remove_int(avl, 934);
   avl = remove_int(avl, 314);
-  avl = gpr_avl_add(avl, box(101), box(2085));
+  avl = gpr_avl_add(avl, box(101), box(2085), NULL);
   avl = remove_int(avl, 938);
   avl = remove_int(avl, 1010);
-  avl = gpr_avl_add(avl, box(579), box(2088));
+  avl = gpr_avl_add(avl, box(579), box(2088), NULL);
   avl = remove_int(avl, 798);
   avl = remove_int(avl, 88);
-  avl = gpr_avl_add(avl, box(851), box(2091));
+  avl = gpr_avl_add(avl, box(851), box(2091), NULL);
   avl = remove_int(avl, 705);
-  avl = gpr_avl_add(avl, box(26), box(2093));
+  avl = gpr_avl_add(avl, box(26), box(2093), NULL);
   avl = remove_int(avl, 973);
-  avl = gpr_avl_add(avl, box(923), box(2095));
+  avl = gpr_avl_add(avl, box(923), box(2095), NULL);
   avl = remove_int(avl, 668);
-  avl = gpr_avl_add(avl, box(310), box(2097));
-  avl = gpr_avl_add(avl, box(269), box(2098));
+  avl = gpr_avl_add(avl, box(310), box(2097), NULL);
+  avl = gpr_avl_add(avl, box(269), box(2098), NULL);
   avl = remove_int(avl, 173);
-  avl = gpr_avl_add(avl, box(279), box(2100));
+  avl = gpr_avl_add(avl, box(279), box(2100), NULL);
   avl = remove_int(avl, 203);
-  avl = gpr_avl_add(avl, box(411), box(2102));
+  avl = gpr_avl_add(avl, box(411), box(2102), NULL);
   avl = remove_int(avl, 950);
-  avl = gpr_avl_add(avl, box(6), box(2104));
+  avl = gpr_avl_add(avl, box(6), box(2104), NULL);
   avl = remove_int(avl, 400);
   avl = remove_int(avl, 468);
   avl = remove_int(avl, 271);
-  avl = gpr_avl_add(avl, box(627), box(2108));
+  avl = gpr_avl_add(avl, box(627), box(2108), NULL);
   avl = remove_int(avl, 727);
   avl = remove_int(avl, 148);
   avl = remove_int(avl, 98);
@@ -3253,259 +3255,259 @@
   avl = remove_int(avl, 628);
   avl = remove_int(avl, 826);
   avl = remove_int(avl, 664);
-  avl = gpr_avl_add(avl, box(76), box(2117));
+  avl = gpr_avl_add(avl, box(76), box(2117), NULL);
   avl = remove_int(avl, 194);
   avl = remove_int(avl, 18);
-  avl = gpr_avl_add(avl, box(727), box(2120));
+  avl = gpr_avl_add(avl, box(727), box(2120), NULL);
   avl = remove_int(avl, 295);
-  avl = gpr_avl_add(avl, box(645), box(2122));
+  avl = gpr_avl_add(avl, box(645), box(2122), NULL);
   avl = remove_int(avl, 321);
   avl = remove_int(avl, 863);
-  avl = gpr_avl_add(avl, box(824), box(2125));
-  avl = gpr_avl_add(avl, box(651), box(2126));
-  avl = gpr_avl_add(avl, box(804), box(2127));
+  avl = gpr_avl_add(avl, box(824), box(2125), NULL);
+  avl = gpr_avl_add(avl, box(651), box(2126), NULL);
+  avl = gpr_avl_add(avl, box(804), box(2127), NULL);
   avl = remove_int(avl, 307);
-  avl = gpr_avl_add(avl, box(867), box(2129));
+  avl = gpr_avl_add(avl, box(867), box(2129), NULL);
   avl = remove_int(avl, 384);
-  avl = gpr_avl_add(avl, box(819), box(2131));
+  avl = gpr_avl_add(avl, box(819), box(2131), NULL);
   avl = remove_int(avl, 674);
-  avl = gpr_avl_add(avl, box(76), box(2133));
+  avl = gpr_avl_add(avl, box(76), box(2133), NULL);
   avl = remove_int(avl, 898);
-  avl = gpr_avl_add(avl, box(45), box(2135));
-  avl = gpr_avl_add(avl, box(512), box(2136));
+  avl = gpr_avl_add(avl, box(45), box(2135), NULL);
+  avl = gpr_avl_add(avl, box(512), box(2136), NULL);
   avl = remove_int(avl, 773);
   avl = remove_int(avl, 907);
   avl = remove_int(avl, 382);
   avl = remove_int(avl, 95);
   avl = remove_int(avl, 734);
   avl = remove_int(avl, 81);
-  avl = gpr_avl_add(avl, box(348), box(2143));
+  avl = gpr_avl_add(avl, box(348), box(2143), NULL);
   avl = remove_int(avl, 509);
   avl = remove_int(avl, 301);
-  avl = gpr_avl_add(avl, box(861), box(2146));
-  avl = gpr_avl_add(avl, box(918), box(2147));
+  avl = gpr_avl_add(avl, box(861), box(2146), NULL);
+  avl = gpr_avl_add(avl, box(918), box(2147), NULL);
   avl = remove_int(avl, 992);
-  avl = gpr_avl_add(avl, box(356), box(2149));
+  avl = gpr_avl_add(avl, box(356), box(2149), NULL);
   avl = remove_int(avl, 64);
   avl = remove_int(avl, 444);
   avl = remove_int(avl, 741);
-  avl = gpr_avl_add(avl, box(710), box(2153));
-  avl = gpr_avl_add(avl, box(264), box(2154));
+  avl = gpr_avl_add(avl, box(710), box(2153), NULL);
+  avl = gpr_avl_add(avl, box(264), box(2154), NULL);
   avl = remove_int(avl, 347);
   avl = remove_int(avl, 250);
-  avl = gpr_avl_add(avl, box(82), box(2157));
-  avl = gpr_avl_add(avl, box(571), box(2158));
+  avl = gpr_avl_add(avl, box(82), box(2157), NULL);
+  avl = gpr_avl_add(avl, box(571), box(2158), NULL);
   avl = remove_int(avl, 721);
   avl = remove_int(avl, 622);
-  avl = gpr_avl_add(avl, box(950), box(2161));
-  avl = gpr_avl_add(avl, box(94), box(2162));
+  avl = gpr_avl_add(avl, box(950), box(2161), NULL);
+  avl = gpr_avl_add(avl, box(94), box(2162), NULL);
   avl = remove_int(avl, 970);
-  avl = gpr_avl_add(avl, box(815), box(2164));
+  avl = gpr_avl_add(avl, box(815), box(2164), NULL);
   avl = remove_int(avl, 930);
   avl = remove_int(avl, 703);
-  avl = gpr_avl_add(avl, box(432), box(2167));
+  avl = gpr_avl_add(avl, box(432), box(2167), NULL);
   avl = remove_int(avl, 544);
-  avl = gpr_avl_add(avl, box(21), box(2169));
-  avl = gpr_avl_add(avl, box(186), box(2170));
+  avl = gpr_avl_add(avl, box(21), box(2169), NULL);
+  avl = gpr_avl_add(avl, box(186), box(2170), NULL);
   avl = remove_int(avl, 143);
-  avl = gpr_avl_add(avl, box(425), box(2172));
+  avl = gpr_avl_add(avl, box(425), box(2172), NULL);
   avl = remove_int(avl, 769);
-  avl = gpr_avl_add(avl, box(656), box(2174));
+  avl = gpr_avl_add(avl, box(656), box(2174), NULL);
   avl = remove_int(avl, 29);
-  avl = gpr_avl_add(avl, box(464), box(2176));
+  avl = gpr_avl_add(avl, box(464), box(2176), NULL);
   avl = remove_int(avl, 713);
-  avl = gpr_avl_add(avl, box(800), box(2178));
+  avl = gpr_avl_add(avl, box(800), box(2178), NULL);
   avl = remove_int(avl, 621);
-  avl = gpr_avl_add(avl, box(962), box(2180));
+  avl = gpr_avl_add(avl, box(962), box(2180), NULL);
   avl = remove_int(avl, 448);
-  avl = gpr_avl_add(avl, box(878), box(2182));
+  avl = gpr_avl_add(avl, box(878), box(2182), NULL);
   avl = remove_int(avl, 39);
   avl = remove_int(avl, 999);
-  avl = gpr_avl_add(avl, box(182), box(2185));
-  avl = gpr_avl_add(avl, box(429), box(2186));
-  avl = gpr_avl_add(avl, box(598), box(2187));
+  avl = gpr_avl_add(avl, box(182), box(2185), NULL);
+  avl = gpr_avl_add(avl, box(429), box(2186), NULL);
+  avl = gpr_avl_add(avl, box(598), box(2187), NULL);
   avl = remove_int(avl, 551);
-  avl = gpr_avl_add(avl, box(827), box(2189));
-  avl = gpr_avl_add(avl, box(809), box(2190));
+  avl = gpr_avl_add(avl, box(827), box(2189), NULL);
+  avl = gpr_avl_add(avl, box(809), box(2190), NULL);
   avl = remove_int(avl, 438);
   avl = remove_int(avl, 811);
-  avl = gpr_avl_add(avl, box(808), box(2193));
-  avl = gpr_avl_add(avl, box(788), box(2194));
+  avl = gpr_avl_add(avl, box(808), box(2193), NULL);
+  avl = gpr_avl_add(avl, box(788), box(2194), NULL);
   avl = remove_int(avl, 156);
-  avl = gpr_avl_add(avl, box(933), box(2196));
-  avl = gpr_avl_add(avl, box(344), box(2197));
+  avl = gpr_avl_add(avl, box(933), box(2196), NULL);
+  avl = gpr_avl_add(avl, box(344), box(2197), NULL);
   avl = remove_int(avl, 460);
-  avl = gpr_avl_add(avl, box(161), box(2199));
-  avl = gpr_avl_add(avl, box(444), box(2200));
+  avl = gpr_avl_add(avl, box(161), box(2199), NULL);
+  avl = gpr_avl_add(avl, box(444), box(2200), NULL);
   avl = remove_int(avl, 597);
   avl = remove_int(avl, 668);
-  avl = gpr_avl_add(avl, box(703), box(2203));
+  avl = gpr_avl_add(avl, box(703), box(2203), NULL);
   avl = remove_int(avl, 515);
-  avl = gpr_avl_add(avl, box(380), box(2205));
-  avl = gpr_avl_add(avl, box(338), box(2206));
+  avl = gpr_avl_add(avl, box(380), box(2205), NULL);
+  avl = gpr_avl_add(avl, box(338), box(2206), NULL);
   avl = remove_int(avl, 550);
   avl = remove_int(avl, 946);
   avl = remove_int(avl, 714);
   avl = remove_int(avl, 739);
-  avl = gpr_avl_add(avl, box(413), box(2211));
+  avl = gpr_avl_add(avl, box(413), box(2211), NULL);
   avl = remove_int(avl, 450);
-  avl = gpr_avl_add(avl, box(411), box(2213));
-  avl = gpr_avl_add(avl, box(117), box(2214));
-  avl = gpr_avl_add(avl, box(322), box(2215));
-  avl = gpr_avl_add(avl, box(915), box(2216));
-  avl = gpr_avl_add(avl, box(410), box(2217));
-  avl = gpr_avl_add(avl, box(66), box(2218));
+  avl = gpr_avl_add(avl, box(411), box(2213), NULL);
+  avl = gpr_avl_add(avl, box(117), box(2214), NULL);
+  avl = gpr_avl_add(avl, box(322), box(2215), NULL);
+  avl = gpr_avl_add(avl, box(915), box(2216), NULL);
+  avl = gpr_avl_add(avl, box(410), box(2217), NULL);
+  avl = gpr_avl_add(avl, box(66), box(2218), NULL);
   avl = remove_int(avl, 756);
   avl = remove_int(avl, 596);
-  avl = gpr_avl_add(avl, box(882), box(2221));
-  avl = gpr_avl_add(avl, box(930), box(2222));
-  avl = gpr_avl_add(avl, box(36), box(2223));
+  avl = gpr_avl_add(avl, box(882), box(2221), NULL);
+  avl = gpr_avl_add(avl, box(930), box(2222), NULL);
+  avl = gpr_avl_add(avl, box(36), box(2223), NULL);
   avl = remove_int(avl, 742);
-  avl = gpr_avl_add(avl, box(539), box(2225));
-  avl = gpr_avl_add(avl, box(596), box(2226));
+  avl = gpr_avl_add(avl, box(539), box(2225), NULL);
+  avl = gpr_avl_add(avl, box(596), box(2226), NULL);
   avl = remove_int(avl, 82);
   avl = remove_int(avl, 686);
   avl = remove_int(avl, 933);
   avl = remove_int(avl, 42);
   avl = remove_int(avl, 340);
-  avl = gpr_avl_add(avl, box(126), box(2232));
-  avl = gpr_avl_add(avl, box(493), box(2233));
-  avl = gpr_avl_add(avl, box(839), box(2234));
+  avl = gpr_avl_add(avl, box(126), box(2232), NULL);
+  avl = gpr_avl_add(avl, box(493), box(2233), NULL);
+  avl = gpr_avl_add(avl, box(839), box(2234), NULL);
   avl = remove_int(avl, 774);
-  avl = gpr_avl_add(avl, box(337), box(2236));
+  avl = gpr_avl_add(avl, box(337), box(2236), NULL);
   avl = remove_int(avl, 322);
-  avl = gpr_avl_add(avl, box(16), box(2238));
+  avl = gpr_avl_add(avl, box(16), box(2238), NULL);
   avl = remove_int(avl, 73);
   avl = remove_int(avl, 85);
   avl = remove_int(avl, 191);
   avl = remove_int(avl, 541);
-  avl = gpr_avl_add(avl, box(704), box(2243));
+  avl = gpr_avl_add(avl, box(704), box(2243), NULL);
   avl = remove_int(avl, 767);
   avl = remove_int(avl, 1006);
   avl = remove_int(avl, 844);
   avl = remove_int(avl, 742);
-  avl = gpr_avl_add(avl, box(48), box(2248));
-  avl = gpr_avl_add(avl, box(138), box(2249));
-  avl = gpr_avl_add(avl, box(437), box(2250));
-  avl = gpr_avl_add(avl, box(275), box(2251));
+  avl = gpr_avl_add(avl, box(48), box(2248), NULL);
+  avl = gpr_avl_add(avl, box(138), box(2249), NULL);
+  avl = gpr_avl_add(avl, box(437), box(2250), NULL);
+  avl = gpr_avl_add(avl, box(275), box(2251), NULL);
   avl = remove_int(avl, 520);
-  avl = gpr_avl_add(avl, box(1019), box(2253));
+  avl = gpr_avl_add(avl, box(1019), box(2253), NULL);
   avl = remove_int(avl, 955);
-  avl = gpr_avl_add(avl, box(270), box(2255));
+  avl = gpr_avl_add(avl, box(270), box(2255), NULL);
   avl = remove_int(avl, 680);
   avl = remove_int(avl, 698);
-  avl = gpr_avl_add(avl, box(735), box(2258));
-  avl = gpr_avl_add(avl, box(400), box(2259));
+  avl = gpr_avl_add(avl, box(735), box(2258), NULL);
+  avl = gpr_avl_add(avl, box(400), box(2259), NULL);
   avl = remove_int(avl, 991);
-  avl = gpr_avl_add(avl, box(263), box(2261));
+  avl = gpr_avl_add(avl, box(263), box(2261), NULL);
   avl = remove_int(avl, 704);
-  avl = gpr_avl_add(avl, box(757), box(2263));
+  avl = gpr_avl_add(avl, box(757), box(2263), NULL);
   avl = remove_int(avl, 194);
   avl = remove_int(avl, 616);
   avl = remove_int(avl, 784);
-  avl = gpr_avl_add(avl, box(382), box(2267));
-  avl = gpr_avl_add(avl, box(464), box(2268));
-  avl = gpr_avl_add(avl, box(817), box(2269));
+  avl = gpr_avl_add(avl, box(382), box(2267), NULL);
+  avl = gpr_avl_add(avl, box(464), box(2268), NULL);
+  avl = gpr_avl_add(avl, box(817), box(2269), NULL);
   avl = remove_int(avl, 445);
-  avl = gpr_avl_add(avl, box(412), box(2271));
+  avl = gpr_avl_add(avl, box(412), box(2271), NULL);
   avl = remove_int(avl, 525);
-  avl = gpr_avl_add(avl, box(299), box(2273));
-  avl = gpr_avl_add(avl, box(464), box(2274));
-  avl = gpr_avl_add(avl, box(715), box(2275));
+  avl = gpr_avl_add(avl, box(299), box(2273), NULL);
+  avl = gpr_avl_add(avl, box(464), box(2274), NULL);
+  avl = gpr_avl_add(avl, box(715), box(2275), NULL);
   avl = remove_int(avl, 58);
   avl = remove_int(avl, 218);
-  avl = gpr_avl_add(avl, box(961), box(2278));
-  avl = gpr_avl_add(avl, box(491), box(2279));
+  avl = gpr_avl_add(avl, box(961), box(2278), NULL);
+  avl = gpr_avl_add(avl, box(491), box(2279), NULL);
   avl = remove_int(avl, 846);
-  avl = gpr_avl_add(avl, box(762), box(2281));
+  avl = gpr_avl_add(avl, box(762), box(2281), NULL);
   avl = remove_int(avl, 974);
   avl = remove_int(avl, 887);
-  avl = gpr_avl_add(avl, box(498), box(2284));
+  avl = gpr_avl_add(avl, box(498), box(2284), NULL);
   avl = remove_int(avl, 810);
   avl = remove_int(avl, 743);
   avl = remove_int(avl, 22);
   avl = remove_int(avl, 284);
-  avl = gpr_avl_add(avl, box(482), box(2289));
-  avl = gpr_avl_add(avl, box(1021), box(2290));
+  avl = gpr_avl_add(avl, box(482), box(2289), NULL);
+  avl = gpr_avl_add(avl, box(1021), box(2290), NULL);
   avl = remove_int(avl, 155);
   avl = remove_int(avl, 128);
-  avl = gpr_avl_add(avl, box(819), box(2293));
-  avl = gpr_avl_add(avl, box(324), box(2294));
+  avl = gpr_avl_add(avl, box(819), box(2293), NULL);
+  avl = gpr_avl_add(avl, box(324), box(2294), NULL);
   avl = remove_int(avl, 196);
   avl = remove_int(avl, 370);
   avl = remove_int(avl, 753);
   avl = remove_int(avl, 56);
   avl = remove_int(avl, 735);
-  avl = gpr_avl_add(avl, box(272), box(2300));
-  avl = gpr_avl_add(avl, box(474), box(2301));
-  avl = gpr_avl_add(avl, box(719), box(2302));
-  avl = gpr_avl_add(avl, box(236), box(2303));
+  avl = gpr_avl_add(avl, box(272), box(2300), NULL);
+  avl = gpr_avl_add(avl, box(474), box(2301), NULL);
+  avl = gpr_avl_add(avl, box(719), box(2302), NULL);
+  avl = gpr_avl_add(avl, box(236), box(2303), NULL);
   avl = remove_int(avl, 818);
-  avl = gpr_avl_add(avl, box(727), box(2305));
+  avl = gpr_avl_add(avl, box(727), box(2305), NULL);
   avl = remove_int(avl, 892);
   avl = remove_int(avl, 871);
   avl = remove_int(avl, 231);
-  avl = gpr_avl_add(avl, box(62), box(2309));
-  avl = gpr_avl_add(avl, box(953), box(2310));
+  avl = gpr_avl_add(avl, box(62), box(2309), NULL);
+  avl = gpr_avl_add(avl, box(953), box(2310), NULL);
   avl = remove_int(avl, 701);
-  avl = gpr_avl_add(avl, box(193), box(2312));
+  avl = gpr_avl_add(avl, box(193), box(2312), NULL);
   avl = remove_int(avl, 619);
   avl = remove_int(avl, 22);
   avl = remove_int(avl, 804);
   avl = remove_int(avl, 851);
-  avl = gpr_avl_add(avl, box(286), box(2317));
-  avl = gpr_avl_add(avl, box(751), box(2318));
+  avl = gpr_avl_add(avl, box(286), box(2317), NULL);
+  avl = gpr_avl_add(avl, box(751), box(2318), NULL);
   avl = remove_int(avl, 525);
-  avl = gpr_avl_add(avl, box(217), box(2320));
+  avl = gpr_avl_add(avl, box(217), box(2320), NULL);
   avl = remove_int(avl, 336);
-  avl = gpr_avl_add(avl, box(86), box(2322));
-  avl = gpr_avl_add(avl, box(81), box(2323));
-  avl = gpr_avl_add(avl, box(850), box(2324));
+  avl = gpr_avl_add(avl, box(86), box(2322), NULL);
+  avl = gpr_avl_add(avl, box(81), box(2323), NULL);
+  avl = gpr_avl_add(avl, box(850), box(2324), NULL);
   avl = remove_int(avl, 872);
-  avl = gpr_avl_add(avl, box(402), box(2326));
-  avl = gpr_avl_add(avl, box(54), box(2327));
-  avl = gpr_avl_add(avl, box(980), box(2328));
-  avl = gpr_avl_add(avl, box(845), box(2329));
+  avl = gpr_avl_add(avl, box(402), box(2326), NULL);
+  avl = gpr_avl_add(avl, box(54), box(2327), NULL);
+  avl = gpr_avl_add(avl, box(980), box(2328), NULL);
+  avl = gpr_avl_add(avl, box(845), box(2329), NULL);
   avl = remove_int(avl, 1004);
   avl = remove_int(avl, 273);
   avl = remove_int(avl, 879);
-  avl = gpr_avl_add(avl, box(354), box(2333));
-  avl = gpr_avl_add(avl, box(58), box(2334));
-  avl = gpr_avl_add(avl, box(127), box(2335));
+  avl = gpr_avl_add(avl, box(354), box(2333), NULL);
+  avl = gpr_avl_add(avl, box(58), box(2334), NULL);
+  avl = gpr_avl_add(avl, box(127), box(2335), NULL);
   avl = remove_int(avl, 84);
-  avl = gpr_avl_add(avl, box(360), box(2337));
+  avl = gpr_avl_add(avl, box(360), box(2337), NULL);
   avl = remove_int(avl, 648);
   avl = remove_int(avl, 488);
   avl = remove_int(avl, 585);
   avl = remove_int(avl, 230);
-  avl = gpr_avl_add(avl, box(887), box(2342));
+  avl = gpr_avl_add(avl, box(887), box(2342), NULL);
   avl = remove_int(avl, 558);
   avl = remove_int(avl, 958);
-  avl = gpr_avl_add(avl, box(822), box(2345));
+  avl = gpr_avl_add(avl, box(822), box(2345), NULL);
   avl = remove_int(avl, 1004);
   avl = remove_int(avl, 747);
-  avl = gpr_avl_add(avl, box(631), box(2348));
-  avl = gpr_avl_add(avl, box(442), box(2349));
+  avl = gpr_avl_add(avl, box(631), box(2348), NULL);
+  avl = gpr_avl_add(avl, box(442), box(2349), NULL);
   avl = remove_int(avl, 957);
   avl = remove_int(avl, 964);
-  avl = gpr_avl_add(avl, box(10), box(2352));
+  avl = gpr_avl_add(avl, box(10), box(2352), NULL);
   avl = remove_int(avl, 189);
-  avl = gpr_avl_add(avl, box(742), box(2354));
+  avl = gpr_avl_add(avl, box(742), box(2354), NULL);
   avl = remove_int(avl, 108);
-  avl = gpr_avl_add(avl, box(1014), box(2356));
+  avl = gpr_avl_add(avl, box(1014), box(2356), NULL);
   avl = remove_int(avl, 266);
   avl = remove_int(avl, 623);
   avl = remove_int(avl, 697);
-  avl = gpr_avl_add(avl, box(180), box(2360));
+  avl = gpr_avl_add(avl, box(180), box(2360), NULL);
   avl = remove_int(avl, 472);
-  avl = gpr_avl_add(avl, box(567), box(2362));
+  avl = gpr_avl_add(avl, box(567), box(2362), NULL);
   avl = remove_int(avl, 1020);
   avl = remove_int(avl, 273);
-  avl = gpr_avl_add(avl, box(864), box(2365));
-  avl = gpr_avl_add(avl, box(1009), box(2366));
+  avl = gpr_avl_add(avl, box(864), box(2365), NULL);
+  avl = gpr_avl_add(avl, box(1009), box(2366), NULL);
   avl = remove_int(avl, 224);
   avl = remove_int(avl, 81);
-  avl = gpr_avl_add(avl, box(653), box(2369));
+  avl = gpr_avl_add(avl, box(653), box(2369), NULL);
   avl = remove_int(avl, 67);
   avl = remove_int(avl, 102);
   avl = remove_int(avl, 76);
@@ -3513,51 +3515,51 @@
   avl = remove_int(avl, 169);
   avl = remove_int(avl, 232);
   avl = remove_int(avl, 79);
-  avl = gpr_avl_add(avl, box(509), box(2377));
+  avl = gpr_avl_add(avl, box(509), box(2377), NULL);
   avl = remove_int(avl, 900);
   avl = remove_int(avl, 822);
   avl = remove_int(avl, 945);
   avl = remove_int(avl, 356);
-  avl = gpr_avl_add(avl, box(443), box(2382));
-  avl = gpr_avl_add(avl, box(925), box(2383));
+  avl = gpr_avl_add(avl, box(443), box(2382), NULL);
+  avl = gpr_avl_add(avl, box(925), box(2383), NULL);
   avl = remove_int(avl, 994);
   avl = remove_int(avl, 324);
-  avl = gpr_avl_add(avl, box(291), box(2386));
+  avl = gpr_avl_add(avl, box(291), box(2386), NULL);
   avl = remove_int(avl, 94);
   avl = remove_int(avl, 795);
   avl = remove_int(avl, 42);
-  avl = gpr_avl_add(avl, box(613), box(2390));
+  avl = gpr_avl_add(avl, box(613), box(2390), NULL);
   avl = remove_int(avl, 289);
-  avl = gpr_avl_add(avl, box(980), box(2392));
+  avl = gpr_avl_add(avl, box(980), box(2392), NULL);
   avl = remove_int(avl, 316);
-  avl = gpr_avl_add(avl, box(281), box(2394));
-  avl = gpr_avl_add(avl, box(1006), box(2395));
+  avl = gpr_avl_add(avl, box(281), box(2394), NULL);
+  avl = gpr_avl_add(avl, box(1006), box(2395), NULL);
   avl = remove_int(avl, 776);
-  avl = gpr_avl_add(avl, box(108), box(2397));
-  avl = gpr_avl_add(avl, box(918), box(2398));
+  avl = gpr_avl_add(avl, box(108), box(2397), NULL);
+  avl = gpr_avl_add(avl, box(918), box(2398), NULL);
   avl = remove_int(avl, 721);
   avl = remove_int(avl, 563);
-  avl = gpr_avl_add(avl, box(925), box(2401));
+  avl = gpr_avl_add(avl, box(925), box(2401), NULL);
   avl = remove_int(avl, 448);
   avl = remove_int(avl, 198);
   avl = remove_int(avl, 1);
-  avl = gpr_avl_add(avl, box(160), box(2405));
+  avl = gpr_avl_add(avl, box(160), box(2405), NULL);
   avl = remove_int(avl, 515);
-  avl = gpr_avl_add(avl, box(284), box(2407));
-  avl = gpr_avl_add(avl, box(225), box(2408));
+  avl = gpr_avl_add(avl, box(284), box(2407), NULL);
+  avl = gpr_avl_add(avl, box(225), box(2408), NULL);
   avl = remove_int(avl, 304);
-  avl = gpr_avl_add(avl, box(714), box(2410));
-  avl = gpr_avl_add(avl, box(708), box(2411));
-  avl = gpr_avl_add(avl, box(624), box(2412));
+  avl = gpr_avl_add(avl, box(714), box(2410), NULL);
+  avl = gpr_avl_add(avl, box(708), box(2411), NULL);
+  avl = gpr_avl_add(avl, box(624), box(2412), NULL);
   avl = remove_int(avl, 662);
   avl = remove_int(avl, 825);
   avl = remove_int(avl, 383);
   avl = remove_int(avl, 381);
-  avl = gpr_avl_add(avl, box(194), box(2417));
+  avl = gpr_avl_add(avl, box(194), box(2417), NULL);
   avl = remove_int(avl, 280);
   avl = remove_int(avl, 25);
   avl = remove_int(avl, 633);
-  avl = gpr_avl_add(avl, box(897), box(2421));
+  avl = gpr_avl_add(avl, box(897), box(2421), NULL);
   avl = remove_int(avl, 636);
   avl = remove_int(avl, 596);
   avl = remove_int(avl, 757);
@@ -3567,33 +3569,33 @@
   avl = remove_int(avl, 843);
   avl = remove_int(avl, 280);
   avl = remove_int(avl, 911);
-  avl = gpr_avl_add(avl, box(1008), box(2431));
+  avl = gpr_avl_add(avl, box(1008), box(2431), NULL);
   avl = remove_int(avl, 948);
   avl = remove_int(avl, 74);
   avl = remove_int(avl, 571);
-  avl = gpr_avl_add(avl, box(486), box(2435));
-  avl = gpr_avl_add(avl, box(285), box(2436));
+  avl = gpr_avl_add(avl, box(486), box(2435), NULL);
+  avl = gpr_avl_add(avl, box(285), box(2436), NULL);
   avl = remove_int(avl, 304);
   avl = remove_int(avl, 516);
-  avl = gpr_avl_add(avl, box(758), box(2439));
-  avl = gpr_avl_add(avl, box(776), box(2440));
+  avl = gpr_avl_add(avl, box(758), box(2439), NULL);
+  avl = gpr_avl_add(avl, box(776), box(2440), NULL);
   avl = remove_int(avl, 696);
-  avl = gpr_avl_add(avl, box(104), box(2442));
-  avl = gpr_avl_add(avl, box(700), box(2443));
-  avl = gpr_avl_add(avl, box(114), box(2444));
-  avl = gpr_avl_add(avl, box(567), box(2445));
+  avl = gpr_avl_add(avl, box(104), box(2442), NULL);
+  avl = gpr_avl_add(avl, box(700), box(2443), NULL);
+  avl = gpr_avl_add(avl, box(114), box(2444), NULL);
+  avl = gpr_avl_add(avl, box(567), box(2445), NULL);
   avl = remove_int(avl, 620);
-  avl = gpr_avl_add(avl, box(270), box(2447));
+  avl = gpr_avl_add(avl, box(270), box(2447), NULL);
   avl = remove_int(avl, 730);
-  avl = gpr_avl_add(avl, box(749), box(2449));
-  avl = gpr_avl_add(avl, box(443), box(2450));
+  avl = gpr_avl_add(avl, box(749), box(2449), NULL);
+  avl = gpr_avl_add(avl, box(443), box(2450), NULL);
   avl = remove_int(avl, 457);
-  avl = gpr_avl_add(avl, box(571), box(2452));
-  avl = gpr_avl_add(avl, box(626), box(2453));
+  avl = gpr_avl_add(avl, box(571), box(2452), NULL);
+  avl = gpr_avl_add(avl, box(626), box(2453), NULL);
   avl = remove_int(avl, 638);
   avl = remove_int(avl, 313);
 
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 static void test_stress(int amount_of_stress) {
@@ -3616,9 +3618,9 @@
     GPR_ASSERT(i);
     if (rand() < RAND_MAX / 2) {
       added[idx] = i;
-      printf("avl = gpr_avl_add(avl, box(%d), box(%d)); /* d=%d */\n", idx, i,
-             deletions);
-      avl = gpr_avl_add(avl, box(idx), box(i));
+      printf("avl = gpr_avl_add(avl, box(%d), box(%d), NULL); /* d=%d */\n",
+             idx, i, deletions);
+      avl = gpr_avl_add(avl, box(idx), box(i), NULL);
     } else {
       deletions += (added[idx] != 0);
       added[idx] = 0;
@@ -3634,7 +3636,7 @@
     }
   }
 
-  gpr_avl_unref(avl);
+  gpr_avl_unref(avl, NULL);
 }
 
 int main(int argc, char *argv[]) {
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index ad0f3e2..2923927 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "alarm_test",
     srcs = ["alarm_test.c"],
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index f9d88d6..e6372a3 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -144,7 +144,7 @@
     cc = grpc_completion_queue_create(
         grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
-    grpc_cq_begin_op(cc, tag);
+    GPR_ASSERT(grpc_cq_begin_op(cc, tag));
     grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE,
                    do_nothing_end_completion, NULL, &completion);
 
@@ -233,7 +233,7 @@
         grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
     for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
-      grpc_cq_begin_op(cc, tags[i]);
+      GPR_ASSERT(grpc_cq_begin_op(cc, tags[i]));
       grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
                      do_nothing_end_completion, NULL, &completions[i]);
     }
@@ -245,7 +245,7 @@
     }
 
     for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
-      grpc_cq_begin_op(cc, tags[i]);
+      GPR_ASSERT(grpc_cq_begin_op(cc, tags[i]));
       grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
                      do_nothing_end_completion, NULL, &completions[i]);
     }
diff --git a/test/core/surface/completion_queue_threading_test.c b/test/core/surface/completion_queue_threading_test.c
index 366565f..9996b6b 100644
--- a/test/core/surface/completion_queue_threading_test.c
+++ b/test/core/surface/completion_queue_threading_test.c
@@ -107,7 +107,7 @@
   GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
-    grpc_cq_begin_op(cc, tags[i]);
+    GPR_ASSERT(grpc_cq_begin_op(cc, tags[i]));
     grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
                    do_nothing_end_completion, NULL, &completions[i]);
   }
@@ -153,7 +153,7 @@
 
   gpr_log(GPR_INFO, "producer %d phase 1", opt->id);
   for (i = 0; i < TEST_THREAD_EVENTS; i++) {
-    grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1);
+    GPR_ASSERT(grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1));
   }
 
   gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id);
@@ -190,7 +190,8 @@
 
   gpr_log(GPR_INFO, "consumer %d phase 2", opt->id);
   for (;;) {
-    ev = grpc_completion_queue_next(opt->cc, ten_seconds_time(), NULL);
+    ev = grpc_completion_queue_next(opt->cc,
+                                    gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
     switch (ev.type) {
       case GRPC_OP_COMPLETE:
         GPR_ASSERT(ev.success);
diff --git a/test/core/surface/init_test.c b/test/core/surface/init_test.c
index 47900c5..a9e8057 100644
--- a/test/core/surface/init_test.c
+++ b/test/core/surface/init_test.c
@@ -52,6 +52,13 @@
   GPR_ASSERT(g_flag == 2);
 }
 
+static void test_repeatedly() {
+  for (int i = 0; i < 100000; i++) {
+    grpc_init();
+    grpc_shutdown();
+  }
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test(1);
@@ -59,5 +66,6 @@
   test(3);
   test_mixed();
   test_plugin();
+  test_repeatedly();
   return 0;
 }
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index f8a9925..040c0c3 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "bdp_estimator_test",
     srcs = ["bdp_estimator_test.c"],
@@ -29,6 +36,18 @@
 )
 
 grpc_cc_test(
+    name = "byte_stream_test",
+    srcs = ["byte_stream_test.c"],
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_test(
     name = "connectivity_state_test",
     srcs = ["connectivity_state_test.c"],
     language = "C",
diff --git a/test/core/transport/byte_stream_test.c b/test/core/transport/byte_stream_test.c
new file mode 100644
index 0000000..a0c5f96
--- /dev/null
+++ b/test/core/transport/byte_stream_test.c
@@ -0,0 +1,279 @@
+/*
+ *
+ * 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 "src/core/lib/transport/byte_stream.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+
+#include "test/core/util/test_config.h"
+
+//
+// grpc_slice_buffer_stream tests
+//
+
+static void not_called_closure(grpc_exec_ctx *exec_ctx, void *arg,
+                               grpc_error *error) {
+  GPR_ASSERT(false);
+}
+
+static void test_slice_buffer_stream_basic(void) {
+  gpr_log(GPR_DEBUG, "test_slice_buffer_stream_basic");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  // Create and populate slice buffer.
+  grpc_slice_buffer buffer;
+  grpc_slice_buffer_init(&buffer);
+  grpc_slice input[] = {
+      grpc_slice_from_static_string("foo"),
+      grpc_slice_from_static_string("bar"),
+  };
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    grpc_slice_buffer_add(&buffer, input[i]);
+  }
+  // Create byte stream.
+  grpc_slice_buffer_stream stream;
+  grpc_slice_buffer_stream_init(&stream, &buffer, 0);
+  GPR_ASSERT(stream.base.length == 6);
+  grpc_closure closure;
+  GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL,
+                    grpc_schedule_on_exec_ctx);
+  // Read each slice.  Note that next() always returns synchronously.
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    GPR_ASSERT(
+        grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+    grpc_slice output;
+    grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_slice_eq(input[i], output));
+    grpc_slice_unref_internal(&exec_ctx, output);
+  }
+  // Clean up.
+  grpc_byte_stream_destroy(&exec_ctx, &stream.base);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void test_slice_buffer_stream_shutdown(void) {
+  gpr_log(GPR_DEBUG, "test_slice_buffer_stream_shutdown");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  // Create and populate slice buffer.
+  grpc_slice_buffer buffer;
+  grpc_slice_buffer_init(&buffer);
+  grpc_slice input[] = {
+      grpc_slice_from_static_string("foo"),
+      grpc_slice_from_static_string("bar"),
+  };
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    grpc_slice_buffer_add(&buffer, input[i]);
+  }
+  // Create byte stream.
+  grpc_slice_buffer_stream stream;
+  grpc_slice_buffer_stream_init(&stream, &buffer, 0);
+  GPR_ASSERT(stream.base.length == 6);
+  grpc_closure closure;
+  GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL,
+                    grpc_schedule_on_exec_ctx);
+  // Read the first slice.
+  GPR_ASSERT(
+      grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+  grpc_slice output;
+  grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_slice_eq(input[0], output));
+  grpc_slice_unref_internal(&exec_ctx, output);
+  // Now shutdown.
+  grpc_error *shutdown_error =
+      GRPC_ERROR_CREATE_FROM_STATIC_STRING("shutdown error");
+  grpc_byte_stream_shutdown(&exec_ctx, &stream.base,
+                            GRPC_ERROR_REF(shutdown_error));
+  // After shutdown, the next pull() should return the error.
+  GPR_ASSERT(
+      grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+  error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+  GPR_ASSERT(error == shutdown_error);
+  GRPC_ERROR_UNREF(error);
+  GRPC_ERROR_UNREF(shutdown_error);
+  // Clean up.
+  grpc_byte_stream_destroy(&exec_ctx, &stream.base);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+//
+// grpc_caching_byte_stream tests
+//
+
+static void test_caching_byte_stream_basic(void) {
+  gpr_log(GPR_DEBUG, "test_caching_byte_stream_basic");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  // Create and populate slice buffer byte stream.
+  grpc_slice_buffer buffer;
+  grpc_slice_buffer_init(&buffer);
+  grpc_slice input[] = {
+      grpc_slice_from_static_string("foo"),
+      grpc_slice_from_static_string("bar"),
+  };
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    grpc_slice_buffer_add(&buffer, input[i]);
+  }
+  grpc_slice_buffer_stream underlying_stream;
+  grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0);
+  // Create cache and caching stream.
+  grpc_byte_stream_cache cache;
+  grpc_byte_stream_cache_init(&cache, &underlying_stream.base);
+  grpc_caching_byte_stream stream;
+  grpc_caching_byte_stream_init(&stream, &cache);
+  grpc_closure closure;
+  GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL,
+                    grpc_schedule_on_exec_ctx);
+  // Read each slice.  Note that next() always returns synchronously,
+  // because the underlying byte stream always does.
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    GPR_ASSERT(
+        grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+    grpc_slice output;
+    grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_slice_eq(input[i], output));
+    grpc_slice_unref_internal(&exec_ctx, output);
+  }
+  // Clean up.
+  grpc_byte_stream_destroy(&exec_ctx, &stream.base);
+  grpc_byte_stream_cache_destroy(&exec_ctx, &cache);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void test_caching_byte_stream_reset(void) {
+  gpr_log(GPR_DEBUG, "test_caching_byte_stream_reset");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  // Create and populate slice buffer byte stream.
+  grpc_slice_buffer buffer;
+  grpc_slice_buffer_init(&buffer);
+  grpc_slice input[] = {
+      grpc_slice_from_static_string("foo"),
+      grpc_slice_from_static_string("bar"),
+  };
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    grpc_slice_buffer_add(&buffer, input[i]);
+  }
+  grpc_slice_buffer_stream underlying_stream;
+  grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0);
+  // Create cache and caching stream.
+  grpc_byte_stream_cache cache;
+  grpc_byte_stream_cache_init(&cache, &underlying_stream.base);
+  grpc_caching_byte_stream stream;
+  grpc_caching_byte_stream_init(&stream, &cache);
+  grpc_closure closure;
+  GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL,
+                    grpc_schedule_on_exec_ctx);
+  // Read one slice.
+  GPR_ASSERT(
+      grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+  grpc_slice output;
+  grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_slice_eq(input[0], output));
+  grpc_slice_unref_internal(&exec_ctx, output);
+  // Reset the caching stream.  The reads should start over from the
+  // first slice.
+  grpc_caching_byte_stream_reset(&stream);
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    GPR_ASSERT(
+        grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure));
+    error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output);
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_slice_eq(input[i], output));
+    grpc_slice_unref_internal(&exec_ctx, output);
+  }
+  // Clean up.
+  grpc_byte_stream_destroy(&exec_ctx, &stream.base);
+  grpc_byte_stream_cache_destroy(&exec_ctx, &cache);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void test_caching_byte_stream_shared_cache(void) {
+  gpr_log(GPR_DEBUG, "test_caching_byte_stream_shared_cache");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  // Create and populate slice buffer byte stream.
+  grpc_slice_buffer buffer;
+  grpc_slice_buffer_init(&buffer);
+  grpc_slice input[] = {
+      grpc_slice_from_static_string("foo"),
+      grpc_slice_from_static_string("bar"),
+  };
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    grpc_slice_buffer_add(&buffer, input[i]);
+  }
+  grpc_slice_buffer_stream underlying_stream;
+  grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0);
+  // Create cache and two caching streams.
+  grpc_byte_stream_cache cache;
+  grpc_byte_stream_cache_init(&cache, &underlying_stream.base);
+  grpc_caching_byte_stream stream1;
+  grpc_caching_byte_stream_init(&stream1, &cache);
+  grpc_caching_byte_stream stream2;
+  grpc_caching_byte_stream_init(&stream2, &cache);
+  grpc_closure closure;
+  GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL,
+                    grpc_schedule_on_exec_ctx);
+  // Read one slice from stream1.
+  GPR_ASSERT(
+      grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure));
+  grpc_slice output;
+  grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_slice_eq(input[0], output));
+  grpc_slice_unref_internal(&exec_ctx, output);
+  // Read all slices from stream2.
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) {
+    GPR_ASSERT(
+        grpc_byte_stream_next(&exec_ctx, &stream2.base, ~(size_t)0, &closure));
+    error = grpc_byte_stream_pull(&exec_ctx, &stream2.base, &output);
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_slice_eq(input[i], output));
+    grpc_slice_unref_internal(&exec_ctx, output);
+  }
+  // Now read the second slice from stream1.
+  GPR_ASSERT(
+      grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure));
+  error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_slice_eq(input[1], output));
+  grpc_slice_unref_internal(&exec_ctx, output);
+  // Clean up.
+  grpc_byte_stream_destroy(&exec_ctx, &stream1.base);
+  grpc_byte_stream_destroy(&exec_ctx, &stream2.base);
+  grpc_byte_stream_cache_destroy(&exec_ctx, &cache);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  test_slice_buffer_stream_basic();
+  test_slice_buffer_stream_shutdown();
+  test_caching_byte_stream_basic();
+  test_caching_byte_stream_reset();
+  test_caching_byte_stream_shared_cache();
+  return 0;
+}
diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD
index 587e0ae..e3989f7 100644
--- a/test/core/transport/chttp2/BUILD
+++ b/test/core/transport/chttp2/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
diff --git a/test/core/tsi/BUILD b/test/core/tsi/BUILD
index c9e75d0..3bbc50b 100644
--- a/test/core/tsi/BUILD
+++ b/test/core/tsi/BUILD
@@ -16,6 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "transport_security_test",
     srcs = ["transport_security_test.c"],
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index bc3640d..9d899bc 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -16,7 +16,13 @@
 
 licenses(["notice"])  # Apache v2
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 grpc_cc_library(
     name = "gpr_test_util",
diff --git a/test/cpp/codegen/BUILD b/test/cpp/codegen/BUILD
index 984440e..4780800 100644
--- a/test/cpp/codegen/BUILD
+++ b/test/cpp/codegen/BUILD
@@ -16,6 +16,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "codegen_test_full",
     srcs = ["codegen_test_full.cc"],
diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden
index f8c7688..b43c27f 100644
--- a/test/cpp/codegen/compiler_test_golden
+++ b/test/cpp/codegen/compiler_test_golden
@@ -39,6 +39,7 @@
 namespace grpc {
 class CompletionQueue;
 class Channel;
+class RpcService;
 class ServerCompletionQueue;
 class ServerContext;
 }  // namespace grpc
@@ -136,10 +137,10 @@
     ::grpc::ClientAsyncReader< ::grpc::testing::Response>* AsyncMethodA3Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq, void* tag) override;
     ::grpc::ClientReaderWriter< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA4Raw(::grpc::ClientContext* context) override;
     ::grpc::ClientAsyncReaderWriter< ::grpc::testing::Request, ::grpc::testing::Response>* AsyncMethodA4Raw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) override;
-    const ::grpc::internal::RpcMethod rpcmethod_MethodA1_;
-    const ::grpc::internal::RpcMethod rpcmethod_MethodA2_;
-    const ::grpc::internal::RpcMethod rpcmethod_MethodA3_;
-    const ::grpc::internal::RpcMethod rpcmethod_MethodA4_;
+    const ::grpc::RpcMethod rpcmethod_MethodA1_;
+    const ::grpc::RpcMethod rpcmethod_MethodA2_;
+    const ::grpc::RpcMethod rpcmethod_MethodA3_;
+    const ::grpc::RpcMethod rpcmethod_MethodA4_;
   };
   static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
 
@@ -319,7 +320,7 @@
    public:
     WithStreamedUnaryMethod_MethodA1() {
       ::grpc::Service::MarkMethodStreamed(0,
-        new ::grpc::internal::StreamedUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithStreamedUnaryMethod_MethodA1<BaseClass>::StreamedMethodA1, this, std::placeholders::_1, std::placeholders::_2)));
+        new ::grpc::StreamedUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithStreamedUnaryMethod_MethodA1<BaseClass>::StreamedMethodA1, this, std::placeholders::_1, std::placeholders::_2)));
     }
     ~WithStreamedUnaryMethod_MethodA1() override {
       BaseClassMustBeDerivedFromService(this);
@@ -340,7 +341,7 @@
    public:
     WithSplitStreamingMethod_MethodA3() {
       ::grpc::Service::MarkMethodStreamed(2,
-        new ::grpc::internal::SplitServerStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithSplitStreamingMethod_MethodA3<BaseClass>::StreamedMethodA3, this, std::placeholders::_1, std::placeholders::_2)));
+        new ::grpc::SplitServerStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithSplitStreamingMethod_MethodA3<BaseClass>::StreamedMethodA3, this, std::placeholders::_1, std::placeholders::_2)));
     }
     ~WithSplitStreamingMethod_MethodA3() override {
       BaseClassMustBeDerivedFromService(this);
@@ -386,7 +387,7 @@
    private:
     std::shared_ptr< ::grpc::ChannelInterface> channel_;
     ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>* AsyncMethodB1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) override;
-    const ::grpc::internal::RpcMethod rpcmethod_MethodB1_;
+    const ::grpc::RpcMethod rpcmethod_MethodB1_;
   };
   static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
 
@@ -443,7 +444,7 @@
    public:
     WithStreamedUnaryMethod_MethodB1() {
       ::grpc::Service::MarkMethodStreamed(0,
-        new ::grpc::internal::StreamedUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithStreamedUnaryMethod_MethodB1<BaseClass>::StreamedMethodB1, this, std::placeholders::_1, std::placeholders::_2)));
+        new ::grpc::StreamedUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>(std::bind(&WithStreamedUnaryMethod_MethodB1<BaseClass>::StreamedMethodB1, this, std::placeholders::_1, std::placeholders::_2)));
     }
     ~WithStreamedUnaryMethod_MethodB1() override {
       BaseClassMustBeDerivedFromService(this);
diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD
index ae287a4..bd11733 100644
--- a/test/cpp/common/BUILD
+++ b/test/cpp/common/BUILD
@@ -16,6 +16,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "alarm_cpp_test",
     srcs = ["alarm_cpp_test.cc"],
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index ac742c2..27c5492 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -16,10 +16,17 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test")
 
-package(default_visibility=["//visibility:public"]) # Allows external users to implement end2end tests.
+package(
+    default_visibility=["//visibility:public"], # Allows external users to implement end2end tests.
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 grpc_cc_library(
     name = "test_service_impl",
+    testonly = True,
     srcs = ["test_service_impl.cc"],
     hdrs = ["test_service_impl.h"],
     deps = [
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 7b78071..7cb7b26 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -212,14 +212,16 @@
 
 class TestScenario {
  public:
-  TestScenario(bool non_block, const grpc::string& creds_type, bool hcs,
-               const grpc::string& content)
+  TestScenario(bool non_block, bool inproc_stub, const grpc::string& creds_type,
+               bool hcs, const grpc::string& content)
       : disable_blocking(non_block),
+        inproc(inproc_stub),
         health_check_service(hcs),
         credentials_type(creds_type),
         message_content(content) {}
   void Log() const;
   bool disable_blocking;
+  bool inproc;
   bool health_check_service;
   // Although the below grpc::string's are logically const, we can't declare
   // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
@@ -232,6 +234,7 @@
                                 const TestScenario& scenario) {
   return out << "TestScenario{disable_blocking="
              << (scenario.disable_blocking ? "true" : "false")
+             << ", inproc=" << (scenario.inproc ? "true" : "false")
              << ", credentials='" << scenario.credentials_type
              << ", health_check_service="
              << (scenario.health_check_service ? "true" : "false")
@@ -294,7 +297,9 @@
     auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
         GetParam().credentials_type, &args);
     std::shared_ptr<Channel> channel =
-        CreateCustomChannel(server_address_.str(), channel_creds, args);
+        !(GetParam().inproc)
+            ? CreateCustomChannel(server_address_.str(), channel_creds, args)
+            : server_->InProcessChannel(args);
     stub_ = grpc::testing::EchoTestService::NewStub(channel);
   }
 
@@ -512,7 +517,7 @@
   // up until server read is initiated. For write of send_request smaller than
   // the flow control window size, the request can take the free ride with
   // initial metadata due to coalescing, thus write tag:3 will come up here.
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking)
         .Expect(2, true)
         .Expect(3, true)
@@ -523,7 +528,7 @@
 
   srv_stream.Read(&recv_request, tag(4));
 
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get());
   } else {
     Verifier(GetParam().disable_blocking)
@@ -807,7 +812,7 @@
   // up until server read is initiated. For write of send_request smaller than
   // the flow control window size, the request can take the free ride with
   // initial metadata due to coalescing, thus write tag:3 will come up here.
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking)
         .Expect(2, true)
         .Expect(3, true)
@@ -818,7 +823,7 @@
 
   srv_stream.Read(&recv_request, tag(4));
 
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get());
   } else {
     Verifier(GetParam().disable_blocking)
@@ -875,7 +880,7 @@
   // up until server read is initiated. For write of send_request smaller than
   // the flow control window size, the request can take the free ride with
   // initial metadata due to coalescing, thus write tag:3 will come up here.
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking)
         .Expect(2, true)
         .Expect(3, true)
@@ -886,7 +891,7 @@
 
   srv_stream.Read(&recv_request, tag(4));
 
-  if (GetParam().message_content.length() < 65536) {
+  if (GetParam().message_content.length() < 65536 || GetParam().inproc) {
     Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get());
   } else {
     Verifier(GetParam().disable_blocking)
@@ -1223,7 +1228,9 @@
   auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
       GetParam().credentials_type, &args);
   std::shared_ptr<Channel> channel =
-      CreateCustomChannel(server_address_.str(), channel_creds, args);
+      !(GetParam().inproc)
+          ? CreateCustomChannel(server_address_.str(), channel_creds, args)
+          : server_->InProcessChannel(args);
   std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub;
   stub = grpc::testing::UnimplementedEchoService::NewStub(channel);
   EchoRequest send_request;
@@ -1634,13 +1641,17 @@
     // This is expected to succeed in all cases
     cli_stream->WritesDone(tag(7));
     verif.Expect(7, true);
-    got_tag = verif.Next(cq_.get(), ignore_cq_result);
+    // TODO(vjpai): Consider whether the following is too flexible
+    // or whether it should just be reset to ignore_cq_result
+    bool ignore_cq_wd_result =
+        ignore_cq_result || (server_try_cancel == CANCEL_BEFORE_PROCESSING);
+    got_tag = verif.Next(cq_.get(), ignore_cq_wd_result);
     GPR_ASSERT((got_tag == 7) || (got_tag == 11 && want_done_tag));
     if (got_tag == 11) {
       EXPECT_TRUE(srv_ctx.IsCancelled());
       want_done_tag = false;
       // Now get the other entry that we were waiting on
-      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 7);
+      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_wd_result), 7);
     }
 
     // This is expected to fail in all cases i.e for all values of
@@ -1732,8 +1743,14 @@
   std::vector<grpc::string> credentials_types;
   std::vector<grpc::string> messages;
 
-  if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType,
-                                                      nullptr) != nullptr) {
+  auto insec_ok = [] {
+    // Only allow insecure credentials type when it is registered with the
+    // provider. User may create providers that do not have insecure.
+    return GetCredentialsProvider()->GetChannelCredentials(
+               kInsecureCredentialsType, nullptr) != nullptr;
+  };
+
+  if (insec_ok()) {
     credentials_types.push_back(kInsecureCredentialsType);
   }
   auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList();
@@ -1755,14 +1772,19 @@
   // TODO (sreek) Renable tests with health check service after the issue
   // https://github.com/grpc/grpc/issues/11223 is resolved
   for (auto health_check_service : {false}) {
-    for (auto cred = credentials_types.begin(); cred != credentials_types.end();
-         ++cred) {
-      for (auto msg = messages.begin(); msg != messages.end(); msg++) {
-        scenarios.emplace_back(false, *cred, health_check_service, *msg);
+    for (auto msg = messages.begin(); msg != messages.end(); msg++) {
+      for (auto cred = credentials_types.begin();
+           cred != credentials_types.end(); ++cred) {
+        scenarios.emplace_back(false, false, *cred, health_check_service, *msg);
         if (test_disable_blocking) {
-          scenarios.emplace_back(true, *cred, health_check_service, *msg);
+          scenarios.emplace_back(true, false, *cred, health_check_service,
+                                 *msg);
         }
       }
+      if (insec_ok()) {
+        scenarios.emplace_back(false, true, kInsecureCredentialsType,
+                               health_check_service, *msg);
+      }
     }
   }
   return scenarios;
diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc
index 6d3f5a9..e1160ec 100644
--- a/test/cpp/end2end/client_lb_end2end_test.cc
+++ b/test/cpp/end2end/client_lb_end2end_test.cc
@@ -35,6 +35,7 @@
 
 extern "C" {
 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
+#include "src/core/ext/filters/client_channel/subchannel_index.h"
 }
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -331,10 +332,14 @@
   for (size_t i = 0; i < servers_.size(); ++i) {
     ports.emplace_back(servers_[i]->port_);
   }
-  for (size_t i = 0; i < 1000; ++i) {
-    std::random_shuffle(ports.begin(), ports.end());
-    SetNextResolution(ports);
-    if (i % 10 == 0) SendRpc();
+  for (const bool force_creation : {true, false}) {
+    grpc_subchannel_index_test_only_set_force_creation(force_creation);
+    gpr_log(GPR_INFO, "Force subchannel creation: %d", force_creation);
+    for (size_t i = 0; i < 1000; ++i) {
+      std::random_shuffle(ports.begin(), ports.end());
+      SetNextResolution(ports);
+      if (i % 10 == 0) SendRpc();
+    }
   }
   // Check LB policy name for the channel.
   EXPECT_EQ("pick_first", channel_->GetLoadBalancingPolicyName());
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index d72dda3..8bada48 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -193,10 +193,11 @@
 
 class TestScenario {
  public:
-  TestScenario(bool proxy, const grpc::string& creds_type)
-      : use_proxy(proxy), credentials_type(creds_type) {}
+  TestScenario(bool proxy, bool inproc_stub, const grpc::string& creds_type)
+      : use_proxy(proxy), inproc(inproc_stub), credentials_type(creds_type) {}
   void Log() const;
   bool use_proxy;
+  bool inproc;
   // Although the below grpc::string is logically const, we can't declare
   // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
   // manage vector insertion using a copy constructor
@@ -206,8 +207,9 @@
 static std::ostream& operator<<(std::ostream& out,
                                 const TestScenario& scenario) {
   return out << "TestScenario{use_proxy="
-             << (scenario.use_proxy ? "true" : "false") << ", credentials='"
-             << scenario.credentials_type << "'}";
+             << (scenario.use_proxy ? "true" : "false")
+             << ", inproc=" << (scenario.inproc ? "true" : "false")
+             << ", credentials='" << scenario.credentials_type << "'}";
 }
 
 void TestScenario::Log() const {
@@ -273,7 +275,13 @@
       args.SetUserAgentPrefix(user_agent_prefix_);
     }
     args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test");
-    channel_ = CreateCustomChannel(server_address_.str(), channel_creds, args);
+
+    if (!GetParam().inproc) {
+      channel_ =
+          CreateCustomChannel(server_address_.str(), channel_creds, args);
+    } else {
+      channel_ = server_->InProcessChannel(args);
+    }
   }
 
   void ResetStub() {
@@ -633,6 +641,10 @@
 }
 
 TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) {
+  // User-Agent is an HTTP header for HTTP transports only
+  if (GetParam().inproc) {
+    return;
+  }
   user_agent_prefix_ = "custom_prefix";
   ResetStub();
   EchoRequest request;
@@ -1065,6 +1077,10 @@
 }
 
 TEST_P(End2endTest, ChannelState) {
+  if (GetParam().inproc) {
+    return;
+  }
+
   ResetStub();
   // Start IDLE
   EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
@@ -1088,7 +1104,8 @@
 
 // Takes 10s.
 TEST_P(End2endTest, ChannelStateTimeout) {
-  if (GetParam().credentials_type != kInsecureCredentialsType) {
+  if ((GetParam().credentials_type != kInsecureCredentialsType) ||
+      GetParam().inproc) {
     return;
   }
   int port = grpc_pick_unused_port_or_die();
@@ -1548,7 +1565,9 @@
   Status s = stub_->Echo(&context, request, &response);
   EXPECT_FALSE(s.ok());
   EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
-  EXPECT_EQ(s.error_message(), kTestCredsPluginErrorMsg);
+  EXPECT_EQ(s.error_message(),
+            grpc::string("Getting metadata from plugin failed with error: ") +
+                kTestCredsPluginErrorMsg);
 }
 
 TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
@@ -1607,7 +1626,9 @@
   Status s = stub_->Echo(&context, request, &response);
   EXPECT_FALSE(s.ok());
   EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
-  EXPECT_EQ(s.error_message(), kTestCredsPluginErrorMsg);
+  EXPECT_EQ(s.error_message(),
+            grpc::string("Getting metadata from plugin failed with error: ") +
+                kTestCredsPluginErrorMsg);
 }
 
 TEST_P(SecureEnd2endTest, ClientAuthContext) {
@@ -1669,51 +1690,56 @@
 
 std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
                                               bool test_insecure,
-                                              bool test_secure) {
+                                              bool test_secure,
+                                              bool test_inproc) {
   std::vector<TestScenario> scenarios;
   std::vector<grpc::string> credentials_types;
   if (test_secure) {
     credentials_types =
         GetCredentialsProvider()->GetSecureCredentialsTypeList();
   }
-  if (test_insecure) {
-    // Only add insecure credentials type when it is registered with the
+  auto insec_ok = [] {
+    // Only allow insecure credentials type when it is registered with the
     // provider. User may create providers that do not have insecure.
-    if (GetCredentialsProvider()->GetChannelCredentials(
-            kInsecureCredentialsType, nullptr) != nullptr) {
-      credentials_types.push_back(kInsecureCredentialsType);
-    }
+    return GetCredentialsProvider()->GetChannelCredentials(
+               kInsecureCredentialsType, nullptr) != nullptr;
+  };
+  if (test_insecure && insec_ok()) {
+    credentials_types.push_back(kInsecureCredentialsType);
   }
   GPR_ASSERT(!credentials_types.empty());
   for (auto it = credentials_types.begin(); it != credentials_types.end();
        ++it) {
-    scenarios.emplace_back(false, *it);
+    scenarios.emplace_back(false, false, *it);
     if (use_proxy) {
-      scenarios.emplace_back(true, *it);
+      scenarios.emplace_back(true, false, *it);
     }
   }
+  if (test_inproc && insec_ok()) {
+    scenarios.emplace_back(false, true, kInsecureCredentialsType);
+  }
   return scenarios;
 }
 
 INSTANTIATE_TEST_CASE_P(End2end, End2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, true,
-                                                                true)));
+                                                                true, true)));
 
 INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, true,
-                                                                true)));
+                                                                true, true)));
 
 INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(true, true,
-                                                                true)));
+                                                                true, false)));
 
 INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, false,
-                                                                true)));
+                                                                true, false)));
 
 INSTANTIATE_TEST_CASE_P(ResourceQuotaEnd2end, ResourceQuotaEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, true,
-                                                                true)));
+                                                                true, true)));
 
 }  // namespace
 }  // namespace testing
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index 4f839f7..4fef535 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -32,7 +32,6 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 extern "C" {
 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
@@ -46,6 +45,9 @@
 #include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
 // TODO(dgq): Other scenarios in need of testing:
 // - Send a serverlist with faulty ip:port addresses (port > 2^16, etc).
 // - Test reception of invalid serverlist
@@ -72,8 +74,8 @@
 
 using std::chrono::system_clock;
 
-using grpc::lb::v1::LoadBalanceResponse;
 using grpc::lb::v1::LoadBalanceRequest;
+using grpc::lb::v1::LoadBalanceResponse;
 using grpc::lb::v1::LoadBalancer;
 
 namespace grpc {
@@ -130,6 +132,19 @@
     IncreaseResponseCount();
     return status;
   }
+
+  // Returns true on its first invocation, false otherwise.
+  bool Shutdown() {
+    std::unique_lock<std::mutex> lock(mu_);
+    const bool prev = !shutdown_;
+    shutdown_ = true;
+    gpr_log(GPR_INFO, "Backend: shut down");
+    return prev;
+  }
+
+ private:
+  std::mutex mu_;
+  bool shutdown_ = false;
 };
 
 grpc::string Ip4ToPackedString(const char* ip_str) {
@@ -141,22 +156,20 @@
 struct ClientStats {
   size_t num_calls_started = 0;
   size_t num_calls_finished = 0;
-  size_t num_calls_finished_with_drop_for_rate_limiting = 0;
-  size_t num_calls_finished_with_drop_for_load_balancing = 0;
   size_t num_calls_finished_with_client_failed_to_send = 0;
   size_t num_calls_finished_known_received = 0;
+  std::map<grpc::string, size_t> drop_token_counts;
 
   ClientStats& operator+=(const ClientStats& other) {
     num_calls_started += other.num_calls_started;
     num_calls_finished += other.num_calls_finished;
-    num_calls_finished_with_drop_for_rate_limiting +=
-        other.num_calls_finished_with_drop_for_rate_limiting;
-    num_calls_finished_with_drop_for_load_balancing +=
-        other.num_calls_finished_with_drop_for_load_balancing;
     num_calls_finished_with_client_failed_to_send +=
         other.num_calls_finished_with_client_failed_to_send;
     num_calls_finished_known_received +=
         other.num_calls_finished_known_received;
+    for (const auto& p : other.drop_token_counts) {
+      drop_token_counts[p.first] += p.second;
+    }
     return *this;
   }
 };
@@ -172,11 +185,12 @@
         shutdown_(false) {}
 
   Status BalanceLoad(ServerContext* context, Stream* stream) override {
-    gpr_log(GPR_INFO, "LB: BalanceLoad");
+    gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this);
     LoadBalanceRequest request;
     stream->Read(&request);
     IncreaseRequestCount();
-    gpr_log(GPR_INFO, "LB: recv msg '%s'", request.DebugString().c_str());
+    gpr_log(GPR_INFO, "LB[%p]: recv msg '%s'", this,
+            request.DebugString().c_str());
 
     if (client_load_reporting_interval_seconds_ > 0) {
       LoadBalanceResponse initial_response;
@@ -194,41 +208,44 @@
     for (const auto& response_and_delay : responses_and_delays) {
       {
         std::unique_lock<std::mutex> lock(mu_);
-        if (shutdown_) break;
+        if (shutdown_) goto done;
       }
       SendResponse(stream, response_and_delay.first, response_and_delay.second);
     }
     {
       std::unique_lock<std::mutex> lock(mu_);
+      if (shutdown_) goto done;
       serverlist_cond_.wait(lock);
     }
 
     if (client_load_reporting_interval_seconds_ > 0) {
       request.Clear();
       stream->Read(&request);
-      gpr_log(GPR_INFO, "LB: recv client load report msg: '%s'",
+      gpr_log(GPR_INFO, "LB[%p]: recv client load report msg: '%s'", this,
               request.DebugString().c_str());
       GPR_ASSERT(request.has_client_stats());
+      // We need to acquire the lock here in order to prevent the notify_one
+      // below from firing before its corresponding wait is executed.
+      std::lock_guard<std::mutex> lock(mu_);
       client_stats_.num_calls_started +=
           request.client_stats().num_calls_started();
       client_stats_.num_calls_finished +=
           request.client_stats().num_calls_finished();
-      client_stats_.num_calls_finished_with_drop_for_rate_limiting +=
-          request.client_stats()
-              .num_calls_finished_with_drop_for_rate_limiting();
-      client_stats_.num_calls_finished_with_drop_for_load_balancing +=
-          request.client_stats()
-              .num_calls_finished_with_drop_for_load_balancing();
       client_stats_.num_calls_finished_with_client_failed_to_send +=
           request.client_stats()
               .num_calls_finished_with_client_failed_to_send();
       client_stats_.num_calls_finished_known_received +=
           request.client_stats().num_calls_finished_known_received();
-      std::lock_guard<std::mutex> lock(mu_);
+      for (const auto& drop_token_count :
+           request.client_stats().calls_finished_with_drop()) {
+        client_stats_
+            .drop_token_counts[drop_token_count.load_balance_token()] +=
+            drop_token_count.num_calls();
+      }
       load_report_cond_.notify_one();
     }
-
-    gpr_log(GPR_INFO, "LB: done");
+  done:
+    gpr_log(GPR_INFO, "LB[%p]: done", this);
     return Status::OK;
   }
 
@@ -243,21 +260,20 @@
     std::unique_lock<std::mutex> lock(mu_);
     const bool prev = !shutdown_;
     shutdown_ = true;
-    gpr_log(GPR_INFO, "LB: shut down");
+    gpr_log(GPR_INFO, "LB[%p]: shut down", this);
     return prev;
   }
 
   static LoadBalanceResponse BuildResponseForBackends(
-      const std::vector<int>& backend_ports, int num_drops_for_rate_limiting,
-      int num_drops_for_load_balancing) {
+      const std::vector<int>& backend_ports,
+      const std::map<grpc::string, size_t>& drop_token_counts) {
     LoadBalanceResponse response;
-    for (int i = 0; i < num_drops_for_rate_limiting; ++i) {
-      auto* server = response.mutable_server_list()->add_servers();
-      server->set_drop_for_rate_limiting(true);
-    }
-    for (int i = 0; i < num_drops_for_load_balancing; ++i) {
-      auto* server = response.mutable_server_list()->add_servers();
-      server->set_drop_for_load_balancing(true);
+    for (const auto& drop_token_count : drop_token_counts) {
+      for (size_t i = 0; i < drop_token_count.second; ++i) {
+        auto* server = response.mutable_server_list()->add_servers();
+        server->set_drop(true);
+        server->set_load_balance_token(drop_token_count.first);
+      }
     }
     for (const int& backend_port : backend_ports) {
       auto* server = response.mutable_server_list()->add_servers();
@@ -281,13 +297,13 @@
  private:
   void SendResponse(Stream* stream, const LoadBalanceResponse& response,
                     int delay_ms) {
-    gpr_log(GPR_INFO, "LB: sleeping for %d ms...", delay_ms);
+    gpr_log(GPR_INFO, "LB[%p]: sleeping for %d ms...", this, delay_ms);
     if (delay_ms > 0) {
       gpr_sleep_until(
           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                        gpr_time_from_millis(delay_ms, GPR_TIMESPAN)));
     }
-    gpr_log(GPR_INFO, "LB: Woke up! Sending response '%s'",
+    gpr_log(GPR_INFO, "LB[%p]: Woke up! Sending response '%s'", this,
             response.DebugString().c_str());
     IncreaseResponseCount();
     stream->Write(response);
@@ -337,7 +353,7 @@
 
   void TearDown() override {
     for (size_t i = 0; i < backends_.size(); ++i) {
-      backend_servers_[i].Shutdown();
+      if (backends_[i]->Shutdown()) backend_servers_[i].Shutdown();
     }
     for (size_t i = 0; i < balancers_.size(); ++i) {
       if (balancers_[i]->Shutdown()) balancer_servers_[i].Shutdown();
@@ -428,19 +444,24 @@
     explicit ServerThread(const grpc::string& type,
                           const grpc::string& server_host, T* service)
         : type_(type), service_(service) {
+      std::mutex mu;
+      // We need to acquire the lock here in order to prevent the notify_one
+      // by ServerThread::Start from firing before the wait below is hit.
+      std::unique_lock<std::mutex> lock(mu);
       port_ = grpc_pick_unused_port_or_die();
       gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_);
-      std::mutex mu;
       std::condition_variable cond;
       thread_.reset(new std::thread(
           std::bind(&ServerThread::Start, this, server_host, &mu, &cond)));
-      std::unique_lock<std::mutex> lock(mu);
       cond.wait(lock);
       gpr_log(GPR_INFO, "%s server startup complete", type_.c_str());
     }
 
     void Start(const grpc::string& server_host, std::mutex* mu,
                std::condition_variable* cond) {
+      // We need to acquire the lock here in order to prevent the notify_one
+      // below from firing before its corresponding wait is executed.
+      std::lock_guard<std::mutex> lock(*mu);
       std::ostringstream server_address;
       server_address << server_host << ":" << port_;
       ServerBuilder builder;
@@ -448,13 +469,12 @@
                                InsecureServerCredentials());
       builder.RegisterService(service_);
       server_ = builder.BuildAndStart();
-      std::lock_guard<std::mutex> lock(*mu);
       cond->notify_one();
     }
 
     void Shutdown() {
       gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str());
-      server_->Shutdown();
+      server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
       thread_->join();
       gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str());
     }
@@ -491,7 +511,7 @@
 TEST_F(SingleBalancerTest, Vanilla) {
   const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
       0);
   // Make sure that trying to connect works without a call.
   channel_->GetState(true /* try_to_connect */);
@@ -530,7 +550,7 @@
   ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0);
   // Send non-empty serverlist only after kServerlistDelayMs
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
       kServerlistDelayMs);
 
   const auto t0 = system_clock::now();
@@ -572,11 +592,11 @@
 
   // Send a serverlist right away.
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
       0);
   // ... and the same one a bit later.
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
       kServerlistDelayMs);
 
   // Send num_backends/2 requests.
@@ -631,6 +651,61 @@
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
 }
 
+TEST_F(SingleBalancerTest, BackendsRestart) {
+  const size_t kNumRpcsPerAddress = 100;
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
+      0);
+  // Make sure that trying to connect works without a call.
+  channel_->GetState(true /* try_to_connect */);
+  // Send 100 RPCs per server.
+  auto statuses_and_responses =
+      SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
+  }
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backend_servers_[i].service_->request_count());
+  }
+  balancers_[0]->NotifyDoneWithServerlists();
+  // The balancer got a single request.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
+  // and sent a single response.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    if (backends_[i]->Shutdown()) backend_servers_[i].Shutdown();
+  }
+  statuses_and_responses = SendRpc(kMessage_, 1);
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    EXPECT_FALSE(status.ok());
+  }
+  for (size_t i = 0; i < num_backends_; ++i) {
+    backends_.emplace_back(new BackendServiceImpl());
+    backend_servers_.emplace_back(ServerThread<BackendService>(
+        "backend", server_host_, backends_.back().get()));
+  }
+  // The following RPC will fail due to the backend ports having changed. It
+  // will nonetheless exercise the grpclb-roundrobin handling of the RR policy
+  // having gone into shutdown.
+  // TODO(dgq): implement the "backend restart" component as well. We need extra
+  // machinery to either update the LB responses "on the fly" or instruct
+  // backends which ports to restart on.
+  statuses_and_responses = SendRpc(kMessage_, 1);
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    EXPECT_FALSE(status.ok());
+  }
+  // Check LB policy name for the channel.
+  EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
+}
+
 class UpdatesTest : public GrpclbEnd2endTest {
  public:
   UpdatesTest() : GrpclbEnd2endTest(4, 3, 0) {}
@@ -639,12 +714,10 @@
 TEST_F(UpdatesTest, UpdateBalancers) {
   const std::vector<int> first_backend{GetBackendPorts()[0]};
   const std::vector<int> second_backend{GetBackendPorts()[1]};
-
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, 0, 0), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0);
   ScheduleResponseForBalancer(
-      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, 0, 0),
-      0);
+      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0);
 
   // Start servers and send 10 RPCs per server.
   gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
@@ -719,10 +792,9 @@
   const std::vector<int> second_backend{GetBackendPorts()[0]};
 
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, 0, 0), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0);
   ScheduleResponseForBalancer(
-      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, 0, 0),
-      0);
+      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0);
 
   // Start servers and send 10 RPCs per server.
   gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
@@ -802,10 +874,9 @@
   const std::vector<int> second_backend{GetBackendPorts()[1]};
 
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, 0, 0), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0);
   ScheduleResponseForBalancer(
-      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, 0, 0),
-      0);
+      1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0);
 
   // Start servers and send 10 RPCs per server.
   gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
@@ -820,6 +891,7 @@
 
   // Kill balancer 0
   gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************");
+  balancers_[0]->NotifyDoneWithServerlists();
   if (balancers_[0]->Shutdown()) balancer_servers_[0].Shutdown();
   gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************");
 
@@ -893,7 +965,8 @@
 TEST_F(SingleBalancerTest, Drop) {
   const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 1, 2),
+      0, BalancerServiceImpl::BuildResponseForBackends(
+             GetBackendPorts(), {{"rate_limiting", 1}, {"load_balancing", 2}}),
       0);
   // Send 100 RPCs for each server and drop address.
   const auto& statuses_and_responses =
@@ -925,6 +998,49 @@
   EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
 }
 
+TEST_F(SingleBalancerTest, DropAllFirst) {
+  // All registered addresses are marked as "drop".
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(
+             {}, {{"rate_limiting", 1}, {"load_balancing", 1}}),
+      0);
+  const auto& statuses_and_responses = SendRpc(kMessage_, 1);
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy");
+  }
+}
+
+TEST_F(SingleBalancerTest, DropAll) {
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
+      0);
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(
+             {}, {{"rate_limiting", 1}, {"load_balancing", 1}}),
+      1000);
+
+  // First call succeeds.
+  auto statuses_and_responses = SendRpc(kMessage_, 1);
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
+  }
+  // But eventually, the update with only dropped servers is processed and calls
+  // fail.
+  do {
+    statuses_and_responses = SendRpc(kMessage_, 1);
+    ASSERT_EQ(statuses_and_responses.size(), 1UL);
+  } while (statuses_and_responses[0].first.ok());
+  const Status& status = statuses_and_responses[0].first;
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy");
+}
+
 class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest {
  public:
   SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {}
@@ -933,7 +1049,7 @@
 TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
   const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
       0);
   // Send 100 RPCs per server.
   const auto& statuses_and_responses =
@@ -962,17 +1078,17 @@
   EXPECT_EQ(kNumRpcsPerAddress * num_backends_, client_stats.num_calls_started);
   EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
             client_stats.num_calls_finished);
-  EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_rate_limiting);
-  EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_load_balancing);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
   EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
             client_stats.num_calls_finished_known_received);
+  EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre());
 }
 
 TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) {
   const size_t kNumRpcsPerAddress = 3;
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 2, 1),
+      0, BalancerServiceImpl::BuildResponseForBackends(
+             GetBackendPorts(), {{"rate_limiting", 2}, {"load_balancing", 1}}),
       0);
   // Send 100 RPCs for each server and drop address.
   const auto& statuses_and_responses =
@@ -1009,13 +1125,13 @@
             client_stats.num_calls_started);
   EXPECT_EQ(kNumRpcsPerAddress * (num_backends_ + 3),
             client_stats.num_calls_finished);
-  EXPECT_EQ(kNumRpcsPerAddress * 2,
-            client_stats.num_calls_finished_with_drop_for_rate_limiting);
-  EXPECT_EQ(kNumRpcsPerAddress,
-            client_stats.num_calls_finished_with_drop_for_load_balancing);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
   EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
             client_stats.num_calls_finished_known_received);
+  EXPECT_THAT(client_stats.drop_token_counts,
+              ::testing::ElementsAre(
+                  ::testing::Pair("load_balancing", kNumRpcsPerAddress),
+                  ::testing::Pair("rate_limiting", kNumRpcsPerAddress * 2)));
 }
 
 }  // namespace
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 8ca9136..0b63c25 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -19,7 +19,6 @@
 #include <climits>
 #include <thread>
 
-#include <gmock/gmock.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
@@ -31,14 +30,15 @@
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 
-#include <grpc++/test/mock_stream.h>
-
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "src/proto/grpc/testing/echo_mock.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
+#include <grpc++/test/mock_stream.h>
+
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <iostream>
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 542df00..f990a7e 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -151,16 +151,6 @@
   std::mutex mu_;
 };
 
-class TestServiceImplDupPkg
-    : public ::grpc::testing::duplicate::EchoTestService::Service {
- public:
-  Status Echo(ServerContext* context, const EchoRequest* request,
-              EchoResponse* response) override {
-    response->set_message("no package");
-    return Status::OK;
-  }
-};
-
 template <class Service>
 class CommonStressTest {
  public:
@@ -168,63 +158,92 @@
   virtual ~CommonStressTest() {}
   virtual void SetUp() = 0;
   virtual void TearDown() = 0;
-  void ResetStub() {
-    std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureChannelCredentials());
-    stub_ = grpc::testing::EchoTestService::NewStub(channel);
-  }
+  virtual void ResetStub() = 0;
   grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); }
 
  protected:
-  void SetUpStart(ServerBuilder* builder, Service* service) {
-    int port = grpc_pick_unused_port_or_die();
-    server_address_ << "localhost:" << port;
-    // Setup server
-    builder->AddListeningPort(server_address_.str(),
-                              InsecureServerCredentials());
+  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+  std::unique_ptr<Server> server_;
+
+  virtual void SetUpStart(ServerBuilder* builder, Service* service) = 0;
+  void SetUpStartCommon(ServerBuilder* builder, Service* service) {
     builder->RegisterService(service);
     builder->SetMaxMessageSize(
         kMaxMessageSize_);  // For testing max message size.
-    builder->RegisterService(&dup_pkg_service_);
   }
   void SetUpEnd(ServerBuilder* builder) { server_ = builder->BuildAndStart(); }
   void TearDownStart() { server_->Shutdown(); }
   void TearDownEnd() {}
 
  private:
-  std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
-  std::unique_ptr<Server> server_;
-  std::ostringstream server_address_;
   const int kMaxMessageSize_;
-  TestServiceImplDupPkg dup_pkg_service_;
 };
 
-class CommonStressTestSyncServer : public CommonStressTest<TestServiceImpl> {
+template <class Service>
+class CommonStressTestInsecure : public CommonStressTest<Service> {
+ public:
+  void ResetStub() override {
+    std::shared_ptr<Channel> channel =
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
+    this->stub_ = grpc::testing::EchoTestService::NewStub(channel);
+  }
+
+ protected:
+  void SetUpStart(ServerBuilder* builder, Service* service) override {
+    int port = grpc_pick_unused_port_or_die();
+    this->server_address_ << "localhost:" << port;
+    // Setup server
+    builder->AddListeningPort(server_address_.str(),
+                              InsecureServerCredentials());
+    this->SetUpStartCommon(builder, service);
+  }
+
+ private:
+  std::ostringstream server_address_;
+};
+
+template <class Service>
+class CommonStressTestInproc : public CommonStressTest<Service> {
+ public:
+  void ResetStub() override {
+    ChannelArguments args;
+    std::shared_ptr<Channel> channel = this->server_->InProcessChannel(args);
+    this->stub_ = grpc::testing::EchoTestService::NewStub(channel);
+  }
+
+ protected:
+  void SetUpStart(ServerBuilder* builder, Service* service) override {
+    this->SetUpStartCommon(builder, service);
+  }
+};
+
+template <class BaseClass>
+class CommonStressTestSyncServer : public BaseClass {
  public:
   void SetUp() override {
     ServerBuilder builder;
-    SetUpStart(&builder, &service_);
-    SetUpEnd(&builder);
+    this->SetUpStart(&builder, &service_);
+    this->SetUpEnd(&builder);
   }
   void TearDown() override {
-    TearDownStart();
-    TearDownEnd();
+    this->TearDownStart();
+    this->TearDownEnd();
   }
 
  private:
   TestServiceImpl service_;
 };
 
-class CommonStressTestAsyncServer
-    : public CommonStressTest<grpc::testing::EchoTestService::AsyncService> {
+template <class BaseClass>
+class CommonStressTestAsyncServer : public BaseClass {
  public:
   CommonStressTestAsyncServer() : contexts_(kNumAsyncServerThreads * 100) {}
   void SetUp() override {
     shutting_down_ = false;
     ServerBuilder builder;
-    SetUpStart(&builder, &service_);
+    this->SetUpStart(&builder, &service_);
     cq_ = builder.AddCompletionQueue();
-    SetUpEnd(&builder);
+    this->SetUpEnd(&builder);
     for (int i = 0; i < kNumAsyncServerThreads * 100; i++) {
       RefreshContext(i);
     }
@@ -236,7 +255,7 @@
   void TearDown() override {
     {
       std::unique_lock<std::mutex> l(mu_);
-      TearDownStart();
+      this->TearDownStart();
       shutting_down_ = true;
       cq_->Shutdown();
     }
@@ -249,7 +268,7 @@
     bool ignored_ok;
     while (cq_->Next(&ignored_tag, &ignored_ok))
       ;
-    TearDownEnd();
+    this->TearDownEnd();
   }
 
  private:
@@ -332,8 +351,13 @@
   }
 }
 
-typedef ::testing::Types<CommonStressTestSyncServer,
-                         CommonStressTestAsyncServer>
+typedef ::testing::Types<
+    CommonStressTestSyncServer<CommonStressTestInsecure<TestServiceImpl>>,
+    CommonStressTestSyncServer<CommonStressTestInproc<TestServiceImpl>>,
+    CommonStressTestAsyncServer<
+        CommonStressTestInsecure<grpc::testing::EchoTestService::AsyncService>>,
+    CommonStressTestAsyncServer<
+        CommonStressTestInproc<grpc::testing::EchoTestService::AsyncService>>>
     CommonTypes;
 TYPED_TEST_CASE(End2endTest, CommonTypes);
 TYPED_TEST(End2endTest, ThreadStress) {
diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc
index cec9666..6b0350e 100644
--- a/test/cpp/grpclb/grpclb_api_test.cc
+++ b/test/cpp/grpclb/grpclb_api_test.cc
@@ -91,13 +91,13 @@
   auto* server = serverlist->add_servers();
   server->set_ip_address(Ip4ToPackedString("127.0.0.1"));
   server->set_port(12345);
-  server->set_drop_for_rate_limiting(true);
-  server->set_drop_for_load_balancing(false);
+  server->set_load_balance_token("rate_limting");
+  server->set_drop(true);
   server = response.mutable_server_list()->add_servers();
   server->set_ip_address(Ip4ToPackedString("10.0.0.1"));
   server->set_port(54321);
-  server->set_drop_for_rate_limiting(false);
-  server->set_drop_for_load_balancing(true);
+  server->set_load_balance_token("load_balancing");
+  server->set_drop(true);
   auto* expiration_interval = serverlist->mutable_expiration_interval();
   expiration_interval->set_seconds(888);
   expiration_interval->set_nanos(999);
@@ -112,14 +112,14 @@
   EXPECT_EQ(PackedStringToIp(c_serverlist->servers[0]->ip_address),
             "127.0.0.1");
   EXPECT_EQ(c_serverlist->servers[0]->port, 12345);
-  EXPECT_TRUE(c_serverlist->servers[0]->drop_for_rate_limiting);
-  EXPECT_FALSE(c_serverlist->servers[0]->drop_for_load_balancing);
+  EXPECT_STREQ(c_serverlist->servers[0]->load_balance_token, "rate_limting");
+  EXPECT_TRUE(c_serverlist->servers[0]->drop);
   EXPECT_TRUE(c_serverlist->servers[1]->has_ip_address);
 
   EXPECT_EQ(PackedStringToIp(c_serverlist->servers[1]->ip_address), "10.0.0.1");
   EXPECT_EQ(c_serverlist->servers[1]->port, 54321);
-  EXPECT_FALSE(c_serverlist->servers[1]->drop_for_rate_limiting);
-  EXPECT_TRUE(c_serverlist->servers[1]->drop_for_load_balancing);
+  EXPECT_STREQ(c_serverlist->servers[1]->load_balance_token, "load_balancing");
+  EXPECT_TRUE(c_serverlist->servers[1]->drop);
 
   EXPECT_TRUE(c_serverlist->expiration_interval.has_seconds);
   EXPECT_EQ(c_serverlist->expiration_interval.seconds, 888);
diff --git a/test/cpp/interop/BUILD b/test/cpp/interop/BUILD
index 93e01fe..9123bd9 100644
--- a/test/cpp/interop/BUILD
+++ b/test/cpp/interop/BUILD
@@ -14,7 +14,16 @@
 
 licenses(["notice"])  # Apache v2
 
-cc_library(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
+grpc_cc_library(
     name = "server_helper_lib",
     srcs = [
         "server_helper.cc",
@@ -22,21 +31,35 @@
     hdrs = [
         "server_helper.h",
     ],
+    external_deps = [
+        "gflags",
+    ],
+    language = "C++",
     deps = [
         "//test/cpp/util:test_util",
-        "//external:gflags",
     ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "interop_server",
     srcs = [
-        "interop_server.cc",
         "interop_server_bootstrap.cc",
     ],
+    language = "C++",
+    deps = [
+        ":interop_server_lib",
+        "//:grpc++",
+    ],
+)
+
+grpc_cc_library(
+    name = "interop_server_lib",
+    srcs = [
+        "interop_server.cc",
+    ],
+    language = "C++",
     deps = [
         ":server_helper_lib",
-        "//:grpc++",
         "//src/proto/grpc/testing:empty_proto",
         "//src/proto/grpc/testing:messages_proto",
         "//src/proto/grpc/testing:test_proto",
@@ -44,7 +67,7 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "client_helper_lib",
     srcs = [
         "client_helper.cc",
@@ -54,22 +77,73 @@
         "client_helper.h",
         "interop_client.h",
     ],
+    language = "C++",
     deps = [
-        "//test/cpp/util:test_util",
         "//src/proto/grpc/testing:empty_proto",
         "//src/proto/grpc/testing:messages_proto",
         "//src/proto/grpc/testing:test_proto",
         "//test/core/security:oauth2_utils",
         "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
     ],
 )
 
-cc_binary(
-    name = "interop_client",
+grpc_cc_library(
+    name = "interop_client_main",
     srcs = [
         "client.cc",
     ],
+    language = "C++",
     deps = [
         ":client_helper_lib",
     ],
 )
+
+grpc_cc_binary(
+    name = "interop_client",
+    language = "C++",
+    deps = [
+        ":interop_client_main",
+        "//:grpc++",
+    ],
+)
+
+grpc_cc_binary(
+    name = "reconnect_interop_client",
+    srcs = [
+        "reconnect_interop_client.cc",
+    ],
+    deps = [
+        ":client_helper_lib",
+        "//:grpc++",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_binary(
+    name = "reconnect_interop_server",
+    srcs = [
+        "reconnect_interop_server.cc",
+    ],
+    language = "C++",
+    deps = [
+        ":interop_server_lib",
+        "//:grpc++",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_cc_binary(
+    name = "stress_test",
+    srcs = [
+        "stress_interop_client.cc",
+        "stress_interop_client.h",
+        "stress_test.cc",
+    ],
+    deps = [
+        ":client_helper_lib",
+        "//:grpc++",
+        "//test/cpp/util:metrics_server_lib",
+        "//test/cpp/util:test_config",
+    ],
+)
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 10df1cb..5e1bcee 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -16,6 +16,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_test(
     name = "noop-benchmark",
     srcs = ["noop-benchmark.cc"],
diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
index 567ef1c..cb113c5 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
@@ -391,8 +391,9 @@
       MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
         if (!state.KeepRunning()) return;
         // force outgoing window to be yuge
-        s.chttp2_stream()->outgoing_window_delta = 1024 * 1024 * 1024;
-        f.chttp2_transport()->outgoing_window = 1024 * 1024 * 1024;
+        s.chttp2_stream()->flow_control.remote_window_delta =
+            1024 * 1024 * 1024;
+        f.chttp2_transport()->flow_control.remote_window = 1024 * 1024 * 1024;
         grpc_slice_buffer_stream_init(&send_stream, &send_buffer, 0);
         reset_op();
         op.on_complete = c.get();
@@ -517,21 +518,22 @@
   std::unique_ptr<Closure> drain_continue;
   grpc_slice recv_slice;
 
-  std::unique_ptr<Closure> c =
-      MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
-        if (!state.KeepRunning()) return;
-        // force outgoing window to be yuge
-        s.chttp2_stream()->incoming_window_delta = 1024 * 1024 * 1024;
-        f.chttp2_transport()->incoming_window = 1024 * 1024 * 1024;
-        received = 0;
-        reset_op();
-        op.on_complete = do_nothing.get();
-        op.recv_message = true;
-        op.payload->recv_message.recv_message = &recv_stream;
-        op.payload->recv_message.recv_message_ready = drain_start.get();
-        s.Op(&op);
-        f.PushInput(grpc_slice_ref(incoming_data));
-      });
+  std::unique_ptr<Closure> c = MakeClosure([&](grpc_exec_ctx *exec_ctx,
+                                               grpc_error *error) {
+    if (!state.KeepRunning()) return;
+    // force outgoing window to be yuge
+    s.chttp2_stream()->flow_control.local_window_delta = 1024 * 1024 * 1024;
+    s.chttp2_stream()->flow_control.announced_window_delta = 1024 * 1024 * 1024;
+    f.chttp2_transport()->flow_control.announced_window = 1024 * 1024 * 1024;
+    received = 0;
+    reset_op();
+    op.on_complete = do_nothing.get();
+    op.recv_message = true;
+    op.payload->recv_message.recv_message = &recv_stream;
+    op.payload->recv_message.recv_message_ready = drain_start.get();
+    s.Op(&op);
+    f.PushInput(grpc_slice_ref(incoming_data));
+  });
 
   drain_start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
     if (recv_stream == NULL) {
diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc
index 6bb6ad8..a0c0414 100644
--- a/test/cpp/microbenchmarks/bm_cq.cc
+++ b/test/cpp/microbenchmarks/bm_cq.cc
@@ -23,6 +23,7 @@
 #include <grpc++/completion_queue.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc/grpc.h>
+#include <grpc/support/log.h>
 #include "test/cpp/microbenchmarks/helpers.h"
 
 extern "C" {
@@ -69,7 +70,7 @@
 static void DoneWithCompletionOnStack(grpc_exec_ctx* exec_ctx, void* arg,
                                       grpc_cq_completion* completion) {}
 
-class DummyTag final : public internal::CompletionQueueTag {
+class DummyTag final : public CompletionQueueTag {
  public:
   bool FinalizeResult(void** tag, bool* status) override { return true; }
 };
@@ -82,7 +83,7 @@
     grpc_cq_completion completion;
     DummyTag dummy_tag;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_cq_begin_op(c_cq, &dummy_tag);
+    GPR_ASSERT(grpc_cq_begin_op(c_cq, &dummy_tag));
     grpc_cq_end_op(&exec_ctx, c_cq, &dummy_tag, GRPC_ERROR_NONE,
                    DoneWithCompletionOnStack, NULL, &completion);
     grpc_exec_ctx_finish(&exec_ctx);
@@ -102,7 +103,7 @@
   while (state.KeepRunning()) {
     grpc_cq_completion completion;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_cq_begin_op(cq, NULL);
+    GPR_ASSERT(grpc_cq_begin_op(cq, NULL));
     grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE,
                    DoneWithCompletionOnStack, NULL, &completion);
     grpc_exec_ctx_finish(&exec_ctx);
@@ -121,7 +122,7 @@
   while (state.KeepRunning()) {
     grpc_cq_completion completion;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_cq_begin_op(cq, NULL);
+    GPR_ASSERT(grpc_cq_begin_op(cq, NULL));
     grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE,
                    DoneWithCompletionOnStack, NULL, &completion);
     grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
index 1e3830a..f109fe6 100644
--- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
+++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
@@ -41,6 +41,7 @@
 static void* g_tag = (void*)(intptr_t)10;  // Some random number
 static grpc_completion_queue* g_cq;
 static grpc_event_engine_vtable g_vtable;
+static const grpc_event_engine_vtable* g_old_vtable;
 
 static void pollset_shutdown(grpc_exec_ctx* exec_ctx, grpc_pollset* ps,
                              grpc_closure* closure) {
@@ -72,12 +73,12 @@
                                 grpc_pollset_worker** worker, gpr_timespec now,
                                 gpr_timespec deadline) {
   if (gpr_time_cmp(deadline, gpr_time_0(GPR_CLOCK_MONOTONIC)) == 0) {
-    gpr_log(GPR_ERROR, "no-op");
+    gpr_log(GPR_DEBUG, "no-op");
     return GRPC_ERROR_NONE;
   }
 
   gpr_mu_unlock(&ps->mu);
-  grpc_cq_begin_op(g_cq, g_tag);
+  GPR_ASSERT(grpc_cq_begin_op(g_cq, g_tag));
   grpc_cq_end_op(exec_ctx, g_cq, g_tag, GRPC_ERROR_NONE, cq_done_cb, NULL,
                  (grpc_cq_completion*)gpr_malloc(sizeof(grpc_cq_completion)));
   grpc_exec_ctx_flush(exec_ctx);
@@ -98,7 +99,12 @@
 
 static void setup() {
   grpc_init();
+
+  /* Override the event engine with our test event engine (g_vtable); but before
+   * that, save the current event engine in g_old_vtable. We will have to set
+   * g_old_vtable back before calling grpc_shutdown() */
   init_engine_vtable();
+  g_old_vtable = grpc_get_event_engine_test_only();
   grpc_set_event_engine_test_only(&g_vtable);
 
   g_cq = grpc_completion_queue_create_for_next(NULL);
@@ -115,6 +121,10 @@
   }
 
   grpc_completion_queue_destroy(g_cq);
+
+  /* Restore the old event engine before calling grpc_shutdown */
+  grpc_set_event_engine_test_only(g_old_vtable);
+  grpc_shutdown();
 }
 
 /* A few notes about Multi-threaded benchmarks:
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
index f420bd7..0712a40 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
@@ -414,24 +414,34 @@
     ->Apply(StreamingPingPongArgs);
 BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
     ->Apply(StreamingPingPongArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcess, NoOpMutator, NoOpMutator)
+    ->Apply(StreamingPingPongArgs);
 
 BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
                    NoOpMutator)
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
     ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcess, NoOpMutator,
+                   NoOpMutator)
+    ->Range(0, 128 * 1024 * 1024);
 
 BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinInProcessCHTTP2, NoOpMutator,
                    NoOpMutator)
     ->Apply(StreamingPingPongArgs);
 BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinTCP, NoOpMutator, NoOpMutator)
     ->Apply(StreamingPingPongArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, MinInProcess, NoOpMutator, NoOpMutator)
+    ->Apply(StreamingPingPongArgs);
 
 BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinInProcessCHTTP2, NoOpMutator,
                    NoOpMutator)
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinTCP, NoOpMutator, NoOpMutator)
     ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, MinInProcess, NoOpMutator,
+                   NoOpMutator)
+    ->Range(0, 128 * 1024 * 1024);
 
 // Generate Args for StreamingPingPongWithCoalescingApi benchmarks. Currently
 // generates args for only "small streams" (i.e streams with 0, 1 or 2 messages)
@@ -459,6 +469,12 @@
 BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, MinInProcessCHTTP2,
                    NoOpMutator, NoOpMutator)
     ->Apply(StreamingPingPongWithCoalescingApiArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, InProcess,
+                   NoOpMutator, NoOpMutator)
+    ->Apply(StreamingPingPongWithCoalescingApiArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongWithCoalescingApi, MinInProcess,
+                   NoOpMutator, NoOpMutator)
+    ->Apply(StreamingPingPongWithCoalescingApiArgs);
 
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
index fc2d67f..6fbf9da 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
@@ -173,6 +173,8 @@
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
     ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcess)
+    ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
@@ -181,16 +183,20 @@
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
     ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcess)
+    ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair)
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
     ->Range(0, 128 * 1024 * 1024);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinTCP)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinUDS)->Arg(0);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinInProcess)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinSockPair)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, MinInProcessCHTTP2)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinTCP)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinUDS)->Arg(0);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinInProcess)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinSockPair)->Arg(0);
 BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, MinInProcessCHTTP2)->Arg(0);
 
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index aeec7d8..5c44b97 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -73,11 +73,11 @@
       log_.reset(new std::ofstream(fn.str().c_str()));
       write_csv(log_.get(), "t", "iteration", "client_backlog",
                 "server_backlog", "client_t_stall", "client_s_stall",
-                "server_t_stall", "server_s_stall", "client_t_outgoing",
-                "server_t_outgoing", "client_t_incoming", "server_t_incoming",
-                "client_s_outgoing_delta", "server_s_outgoing_delta",
-                "client_s_incoming_delta", "server_s_incoming_delta",
-                "client_s_announce_window", "server_s_announce_window",
+                "server_t_stall", "server_s_stall", "client_t_remote",
+                "server_t_remote", "client_t_announced", "server_t_announced",
+                "client_s_remote_delta", "server_s_remote_delta",
+                "client_s_local_delta", "server_s_local_delta",
+                "client_s_announced_delta", "server_s_announced_delta",
                 "client_peer_iws", "client_local_iws", "client_sent_iws",
                 "client_acked_iws", "server_peer_iws", "server_local_iws",
                 "server_sent_iws", "server_acked_iws", "client_queued_bytes",
@@ -127,14 +127,15 @@
         client->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr,
         server->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != nullptr,
         server->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr,
-        client->outgoing_window, server->outgoing_window,
-        client->incoming_window, server->incoming_window,
-        client_stream ? client_stream->outgoing_window_delta : -1,
-        server_stream ? server_stream->outgoing_window_delta : -1,
-        client_stream ? client_stream->incoming_window_delta : -1,
-        server_stream ? server_stream->incoming_window_delta : -1,
-        client_stream ? client_stream->announce_window : -1,
-        server_stream ? server_stream->announce_window : -1,
+        client->flow_control.remote_window, server->flow_control.remote_window,
+        client->flow_control.announced_window,
+        server->flow_control.announced_window,
+        client_stream ? client_stream->flow_control.remote_window_delta : -1,
+        server_stream ? server_stream->flow_control.remote_window_delta : -1,
+        client_stream ? client_stream->flow_control.local_window_delta : -1,
+        server_stream ? server_stream->flow_control.local_window_delta : -1,
+        client_stream ? client_stream->flow_control.announced_window_delta : -1,
+        server_stream ? server_stream->flow_control.announced_window_delta : -1,
         client->settings[GRPC_PEER_SETTINGS]
                         [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
         client->settings[GRPC_LOCAL_SETTINGS]
diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
index ee2d5ec..9af7512 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
@@ -132,6 +132,10 @@
     ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinUDS, NoOpMutator, NoOpMutator)
     ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator, NoOpMutator)
+    ->Apply(SweepSizesArgs);
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinInProcess, NoOpMutator, NoOpMutator)
+    ->Apply(SweepSizesArgs);
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator)
     ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, MinSockPair, NoOpMutator, NoOpMutator)
@@ -191,6 +195,56 @@
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
                    Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
     ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<100>, 1>,
+                   NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomBinaryMetadata<100>, 2>,
+                   NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess,
+                   Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcess, NoOpMutator,
+                   Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
+    ->Args({0, 0});
 
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc
index 683f470..1fc1f2f 100644
--- a/test/cpp/microbenchmarks/bm_pollset.cc
+++ b/test/cpp/microbenchmarks/bm_pollset.cc
@@ -149,7 +149,7 @@
     grpc_pollset_add_fd(&exec_ctx, ps, fd);
     grpc_exec_ctx_flush(&exec_ctx);
   }
-  grpc_fd_orphan(&exec_ctx, fd, NULL, NULL, "xxx");
+  grpc_fd_orphan(&exec_ctx, fd, NULL, NULL, false /* already_closed */, "xxx");
   grpc_closure shutdown_ps_closure;
   GRPC_CLOSURE_INIT(&shutdown_ps_closure, shutdown_ps, ps,
                     grpc_schedule_on_exec_ctx);
@@ -247,7 +247,8 @@
   while (!done) {
     GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, NULL, now, deadline));
   }
-  grpc_fd_orphan(&exec_ctx, wakeup, NULL, NULL, "done");
+  grpc_fd_orphan(&exec_ctx, wakeup, NULL, NULL, false /* already_closed */,
+                 "done");
   wakeup_fd.read_fd = 0;
   grpc_closure shutdown_ps_closure;
   GRPC_CLOSURE_INIT(&shutdown_ps_closure, shutdown_ps, ps,
diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h
index 2320086..5477b86 100644
--- a/test/cpp/microbenchmarks/fullstack_fixtures.h
+++ b/test/cpp/microbenchmarks/fullstack_fixtures.h
@@ -66,14 +66,21 @@
   FullstackFixture(Service* service, const FixtureConfiguration& config,
                    const grpc::string& address) {
     ServerBuilder b;
-    b.AddListeningPort(address, InsecureServerCredentials());
+    if (address.length() > 0) {
+      b.AddListeningPort(address, InsecureServerCredentials());
+    }
     cq_ = b.AddCompletionQueue(true);
     b.RegisterService(service);
     config.ApplyCommonServerBuilderConfig(&b);
     server_ = b.BuildAndStart();
     ChannelArguments args;
     config.ApplyCommonChannelArguments(&args);
-    channel_ = CreateCustomChannel(address, InsecureChannelCredentials(), args);
+    if (address.length() > 0) {
+      channel_ =
+          CreateCustomChannel(address, InsecureChannelCredentials(), args);
+    } else {
+      channel_ = server_->InProcessChannel(args);
+    }
   }
 
   virtual ~FullstackFixture() {
@@ -139,6 +146,15 @@
   }
 };
 
+class InProcess : public FullstackFixture {
+ public:
+  InProcess(Service* service,
+            const FixtureConfiguration& fixture_configuration =
+                FixtureConfiguration())
+      : FullstackFixture(service, fixture_configuration, "") {}
+  ~InProcess() {}
+};
+
 class EndpointPairFixture : public BaseFixture {
  public:
   EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints,
@@ -279,6 +295,7 @@
 
 typedef MinStackize<TCP> MinTCP;
 typedef MinStackize<UDS> MinUDS;
+typedef MinStackize<InProcess> MinInProcess;
 typedef MinStackize<SockPair> MinSockPair;
 typedef MinStackize<InProcessCHTTP2> MinInProcessCHTTP2;
 
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index 4d8b3b4..b3348b7 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -16,6 +16,13 @@
 
 load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary")
 
+package(
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
+
 grpc_cc_library(
     name = "parse_json",
     srcs = ["parse_json.cc"],
@@ -52,9 +59,6 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
-    external_deps = [
-        "gtest",
-    ],
 )
 
 grpc_cc_library(
@@ -77,6 +81,7 @@
         "//src/proto/grpc/testing:services_proto",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
     ],
 )
 
@@ -121,6 +126,7 @@
         "//:gpr",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_config",
         "//test/cpp/util:test_util",
     ],
 )
@@ -131,6 +137,7 @@
     deps = [
         ":histogram",
         ":interarrival",
+        "//test/cpp/util:test_config",
     ],
 )
 
@@ -141,6 +148,8 @@
         ":benchmark_config",
         ":driver_impl",
         "//:grpc++",
+        "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
     ],
     external_deps = [
         "gflags",
@@ -154,6 +163,8 @@
         ":benchmark_config",
         ":driver_impl",
         ":qps_worker_impl",
+        "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
     ],
 )
 
@@ -164,6 +175,8 @@
         ":benchmark_config",
         ":driver_impl",
         "//:grpc++",
+        "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
     ],
 )
 
diff --git a/test/cpp/qps/benchmark_config.cc b/test/cpp/qps/benchmark_config.cc
index 8f53670..fb1e060 100644
--- a/test/cpp/qps/benchmark_config.cc
+++ b/test/cpp/qps/benchmark_config.cc
@@ -54,10 +54,6 @@
 namespace grpc {
 namespace testing {
 
-void InitBenchmark(int* argc, char*** argv, bool remove_flags) {
-  ParseCommandLineFlags(argc, argv, remove_flags);
-}
-
 static std::shared_ptr<Reporter> InitBenchmarkReporters() {
   auto* composite_reporter = new CompositeReporter;
   if (FLAGS_enable_log_reporter) {
diff --git a/test/cpp/qps/benchmark_config.h b/test/cpp/qps/benchmark_config.h
index 054dbb2..d3d6910 100644
--- a/test/cpp/qps/benchmark_config.h
+++ b/test/cpp/qps/benchmark_config.h
@@ -20,15 +20,12 @@
 #define GRPC_TEST_CPP_UTIL_BENCHMARK_CONFIG_H
 
 #include <memory>
-#include <vector>
 
 #include "test/cpp/qps/report.h"
 
 namespace grpc {
 namespace testing {
 
-void InitBenchmark(int* argc, char*** argv, bool remove_flags);
-
 /** Returns the benchmark Reporter instance.
  *
  * The returned instance will take care of generating reports for all the actual
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index e759446..6c4d92e 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -39,6 +39,7 @@
 #include "test/cpp/qps/interarrival.h"
 #include "test/cpp/qps/usage_timer.h"
 #include "test/cpp/util/create_test_channel.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 namespace testing {
@@ -88,9 +89,7 @@
     if (payload_config.has_bytebuf_params()) {
       std::unique_ptr<char[]> buf(
           new char[payload_config.bytebuf_params().req_size()]);
-      grpc_slice s = grpc_slice_from_copied_buffer(
-          buf.get(), payload_config.bytebuf_params().req_size());
-      Slice slice(s, Slice::STEAL_REF);
+      Slice slice(buf.get(), payload_config.bytebuf_params().req_size());
       *req = ByteBuffer(&slice, 1);
     } else {
       GPR_ASSERT(false);  // not appropriate for this specialization
@@ -407,9 +406,18 @@
       ChannelArguments args;
       args.SetInt("shard_to_ensure_no_subchannel_merges", shard);
       set_channel_args(config, &args);
+
+      grpc::string type;
+      if (config.has_security_params() &&
+          config.security_params().cred_type().empty()) {
+        type = kTlsCredentialsType;
+      } else {
+        type = config.security_params().cred_type();
+      }
+
       channel_ = CreateTestChannel(
-          target, config.security_params().server_host_override(),
-          config.has_security_params(), !config.security_params().use_test_ca(),
+          target, type, config.security_params().server_host_override(),
+          !config.security_params().use_test_ca(),
           std::shared_ptr<CallCredentials>(), args);
       gpr_log(GPR_INFO, "Connecting to %s", target.c_str());
       GPR_ASSERT(channel_->WaitForConnected(
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 6b93492..5d212f1 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -140,7 +140,7 @@
         if (*stream) {
           // forcibly cancel the streams, then finish
           context_[i].TryCancel();
-          (*stream)->Finish();
+          (*stream)->Finish().IgnoreError();
           // don't log any error message on !ok since this was canceled
         }
       });
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index fbd8d1b..4458e38 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -40,6 +40,7 @@
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/qps_worker.h"
 #include "test/cpp/qps/stats.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 using std::list;
 using std::thread;
@@ -172,13 +173,26 @@
       sum(result->client_stats(), CliPollCount) / histogram.Count());
   result->mutable_summary()->set_server_polls_per_request(
       sum(result->server_stats(), SvrPollCount) / histogram.Count());
+
+  auto server_queries_per_cpu_sec =
+      histogram.Count() / (sum(result->server_stats(), ServerSystemTime) +
+                           sum(result->server_stats(), ServerUserTime));
+  auto client_queries_per_cpu_sec =
+      histogram.Count() / (sum(result->client_stats(), SystemTime) +
+                           sum(result->client_stats(), UserTime));
+
+  result->mutable_summary()->set_server_queries_per_cpu_sec(
+      server_queries_per_cpu_sec);
+  result->mutable_summary()->set_client_queries_per_cpu_sec(
+      client_queries_per_cpu_sec);
 }
 
 std::unique_ptr<ScenarioResult> RunScenario(
     const ClientConfig& initial_client_config, size_t num_clients,
     const ServerConfig& initial_server_config, size_t num_servers,
     int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count,
-    const char* qps_server_target_override) {
+    const grpc::string& qps_server_target_override,
+    const grpc::string& credential_type) {
   // Log everything from the driver
   gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
 
@@ -214,7 +228,7 @@
     }
 
     int driver_port = grpc_pick_unused_port_or_die();
-    local_workers.emplace_back(new QpsWorker(driver_port));
+    local_workers.emplace_back(new QpsWorker(driver_port, 0, credential_type));
     char addr[256];
     sprintf(addr, "localhost:%d", driver_port);
     if (spawn_local_worker_count < 0) {
@@ -246,12 +260,14 @@
   };
   std::vector<ServerData> servers(num_servers);
   std::unordered_map<string, std::deque<int>> hosts_cores;
+  ChannelArguments channel_args;
 
   for (size_t i = 0; i < num_servers; i++) {
     gpr_log(GPR_INFO, "Starting server on %s (worker #%" PRIuPTR ")",
             workers[i].c_str(), i);
-    servers[i].stub = WorkerService::NewStub(
-        CreateChannel(workers[i], InsecureChannelCredentials()));
+    servers[i].stub = WorkerService::NewStub(CreateChannel(
+        workers[i], GetCredentialsProvider()->GetChannelCredentials(
+                        credential_type, &channel_args)));
 
     ServerConfig server_config = initial_server_config;
     if (server_config.core_limit() != 0) {
@@ -269,8 +285,7 @@
     if (!servers[i].stream->Read(&init_status)) {
       gpr_log(GPR_ERROR, "Server %zu did not yield initial status", i);
     }
-    if (qps_server_target_override != NULL &&
-        strlen(qps_server_target_override) > 0) {
+    if (qps_server_target_override.length() > 0) {
       // overriding the qps server target only works if there is 1 server
       GPR_ASSERT(num_servers == 1);
       client_config.add_server_targets(qps_server_target_override);
@@ -298,7 +313,8 @@
     gpr_log(GPR_INFO, "Starting client on %s (worker #%" PRIuPTR ")",
             worker.c_str(), i + num_servers);
     clients[i].stub = WorkerService::NewStub(
-        CreateChannel(worker, InsecureChannelCredentials()));
+        CreateChannel(worker, GetCredentialsProvider()->GetChannelCredentials(
+                                  credential_type, &channel_args)));
     ClientConfig per_client_config = client_config;
 
     if (initial_client_config.core_limit() != 0) {
@@ -483,16 +499,19 @@
   return result;
 }
 
-bool RunQuit() {
+bool RunQuit(const grpc::string& credential_type) {
   // Get client, server lists
   bool result = true;
   auto workers = get_workers("QPS_WORKERS");
   if (workers.size() == 0) {
     return false;
   }
+
+  ChannelArguments channel_args;
   for (size_t i = 0; i < workers.size(); i++) {
-    auto stub = WorkerService::NewStub(
-        CreateChannel(workers[i], InsecureChannelCredentials()));
+    auto stub = WorkerService::NewStub(CreateChannel(
+        workers[i], GetCredentialsProvider()->GetChannelCredentials(
+                        credential_type, &channel_args)));
     Void dummy;
     grpc::ClientContext ctx;
     ctx.set_wait_for_ready(true);
diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h
index def32c6..29f2776 100644
--- a/test/cpp/qps/driver.h
+++ b/test/cpp/qps/driver.h
@@ -31,9 +31,10 @@
     const grpc::testing::ClientConfig& client_config, size_t num_clients,
     const grpc::testing::ServerConfig& server_config, size_t num_servers,
     int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count,
-    const char* qps_server_target_override = "");
+    const grpc::string& qps_server_target_override,
+    const grpc::string& credential_type);
 
-bool RunQuit();
+bool RunQuit(const grpc::string& credential_type);
 }  // namespace testing
 }  // namespace grpc
 
diff --git a/test/cpp/qps/qps_interarrival_test.cc b/test/cpp/qps/qps_interarrival_test.cc
index d19266f..87f09e8 100644
--- a/test/cpp/qps/qps_interarrival_test.cc
+++ b/test/cpp/qps/qps_interarrival_test.cc
@@ -23,6 +23,7 @@
 #include <grpc/support/histogram.h>
 
 #include "test/cpp/qps/interarrival.h"
+#include "test/cpp/util/test_config.h"
 
 using grpc::testing::RandomDistInterface;
 using grpc::testing::InterarrivalTimer;
@@ -50,6 +51,8 @@
 using grpc::testing::ExpDist;
 
 int main(int argc, char **argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+
   RunTest(ExpDist(10.0), 5, std::string("Exponential(10)"));
   return 0;
 }
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
index 590c22e..cca59f6 100644
--- a/test/cpp/qps/qps_json_driver.cc
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -30,6 +30,8 @@
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/parse_json.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 DEFINE_string(scenarios_file, "",
               "JSON file containing an array of Scenario objects");
@@ -60,6 +62,9 @@
 
 DEFINE_string(json_file_out, "", "File to write the JSON output to.");
 
+DEFINE_string(credential_type, grpc::testing::kInsecureCredentialsType,
+              "Credential type for communication with workers");
+
 namespace grpc {
 namespace testing {
 
@@ -71,7 +76,7 @@
                   scenario.server_config(), scenario.num_servers(),
                   scenario.warmup_seconds(), scenario.benchmark_seconds(),
                   scenario.spawn_local_worker_count(),
-                  FLAGS_qps_server_target_override.c_str());
+                  FLAGS_qps_server_target_override, FLAGS_credential_type);
 
   // Amend the result with scenario config. Eventually we should adjust
   // RunScenario contract so we don't need to touch the result here.
@@ -83,6 +88,7 @@
   GetReporter()->ReportTimes(*result);
   GetReporter()->ReportCpuUsage(*result);
   GetReporter()->ReportPollCount(*result);
+  GetReporter()->ReportQueriesPerCpuSec(*result);
 
   for (int i = 0; *success && i < result->client_success_size(); i++) {
     *success = result->client_success(i);
@@ -184,7 +190,7 @@
   } else if (scjson) {
     json = FLAGS_scenarios_json.c_str();
   } else if (FLAGS_quit) {
-    return RunQuit();
+    return RunQuit(FLAGS_credential_type);
   }
 
   // Parse into an array of scenarios
@@ -219,7 +225,7 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
+  grpc::testing::InitTest(&argc, &argv, true);
 
   bool ok = grpc::testing::QpsDriver();
 
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index 28dec4f..069b3fa 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -24,6 +24,8 @@
 #include "test/cpp/qps/benchmark_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 namespace testing {
@@ -47,8 +49,8 @@
   server_config.set_server_type(ASYNC_SERVER);
   server_config.set_async_server_threads(8);
 
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
+  const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP,
+                                  BENCHMARK, -2, "", kInsecureCredentialsType);
 
   GetReporter()->ReportQPSPerCore(*result);
   GetReporter()->ReportLatency(*result);
@@ -58,7 +60,7 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
+  grpc::testing::InitTest(&argc, &argv, true);
 
   grpc::testing::RunQPS();
 
diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc
deleted file mode 100644
index 6ab2102..0000000
--- a/test/cpp/qps/qps_test.cc
+++ /dev/null
@@ -1,64 +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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/benchmark_config.h"
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 20;
-static const int BENCHMARK = 20;
-
-static void RunQPS() {
-  gpr_log(GPR_INFO, "Running QPS test");
-
-  ClientConfig client_config;
-  client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(100);
-  client_config.set_client_channels(64);
-  client_config.set_async_client_threads(8);
-  client_config.set_rpc_type(STREAMING);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(ASYNC_SERVER);
-  server_config.set_async_server_threads(8);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPSPerCore(*result);
-  GetReporter()->ReportLatency(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunQPS();
-
-  return 0;
-}
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index 10bc542..d20bc1b 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -41,6 +41,7 @@
 #include "test/cpp/qps/client.h"
 #include "test/cpp/qps/server.h"
 #include "test/cpp/util/create_test_channel.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 namespace testing {
@@ -263,7 +264,8 @@
   QpsWorker* worker_;
 };
 
-QpsWorker::QpsWorker(int driver_port, int server_port) {
+QpsWorker::QpsWorker(int driver_port, int server_port,
+                     const grpc::string& credential_type) {
   impl_.reset(new WorkerServiceImpl(server_port, this));
   gpr_atm_rel_store(&done_, static_cast<gpr_atm>(0));
 
@@ -271,7 +273,9 @@
   gpr_join_host_port(&server_address, "::", driver_port);
 
   ServerBuilder builder;
-  builder.AddListeningPort(server_address, InsecureServerCredentials());
+  builder.AddListeningPort(
+      server_address,
+      GetCredentialsProvider()->GetServerCredentials(credential_type));
   builder.RegisterService(impl_.get());
 
   gpr_free(server_address);
diff --git a/test/cpp/qps/qps_worker.h b/test/cpp/qps/qps_worker.h
index c8a7be9..360125f 100644
--- a/test/cpp/qps/qps_worker.h
+++ b/test/cpp/qps/qps_worker.h
@@ -21,6 +21,7 @@
 
 #include <memory>
 
+#include <grpc++/support/config.h>
 #include <grpc/support/atm.h>
 
 namespace grpc {
@@ -33,7 +34,8 @@
 
 class QpsWorker {
  public:
-  explicit QpsWorker(int driver_port, int server_port = 0);
+  explicit QpsWorker(int driver_port, int server_port,
+                     const grpc::string& credential_type);
   ~QpsWorker();
 
   bool Done() const;
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 809c563..a45b10b 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -71,6 +71,12 @@
   }
 }
 
+void CompositeReporter::ReportQueriesPerCpuSec(const ScenarioResult& result) {
+  for (size_t i = 0; i < reporters_.size(); ++i) {
+    reporters_[i]->ReportQueriesPerCpuSec(result);
+  }
+}
+
 void GprLogReporter::ReportQPS(const ScenarioResult& result) {
   gpr_log(GPR_INFO, "QPS: %.1f", result.summary().qps());
   if (result.summary().failed_requests_per_second() > 0) {
@@ -119,6 +125,13 @@
           result.summary().server_polls_per_request());
 }
 
+void GprLogReporter::ReportQueriesPerCpuSec(const ScenarioResult& result) {
+  gpr_log(GPR_INFO, "Server Queries/CPU-sec: %.2f",
+          result.summary().server_queries_per_cpu_sec());
+  gpr_log(GPR_INFO, "Client Queries/CPU-sec: %.2f",
+          result.summary().client_queries_per_cpu_sec());
+}
+
 void JsonReporter::ReportQPS(const ScenarioResult& result) {
   grpc::string json_string =
       SerializeJson(result, "type.googleapis.com/grpc.testing.ScenarioResult");
@@ -147,6 +160,10 @@
   // NOP - all reporting is handled by ReportQPS.
 }
 
+void JsonReporter::ReportQueriesPerCpuSec(const ScenarioResult& result) {
+  // NOP - all reporting is handled by ReportQPS.
+}
+
 void RpcReporter::ReportQPS(const ScenarioResult& result) {
   grpc::ClientContext context;
   grpc::Status status;
@@ -183,5 +200,9 @@
   // NOP - all reporting is handled by ReportQPS.
 }
 
+void RpcReporter::ReportQueriesPerCpuSec(const ScenarioResult& result) {
+  // NOP - all reporting is handled by ReportQPS.
+}
+
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 0bd398f..321be2a 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -64,6 +64,9 @@
   /** Reports client and server poll usage inside completion queue. */
   virtual void ReportPollCount(const ScenarioResult& result) = 0;
 
+  /** Reports queries per cpu-sec. */
+  virtual void ReportQueriesPerCpuSec(const ScenarioResult& result) = 0;
+
  private:
   const string name_;
 };
@@ -82,6 +85,7 @@
   void ReportTimes(const ScenarioResult& result) override;
   void ReportCpuUsage(const ScenarioResult& result) override;
   void ReportPollCount(const ScenarioResult& result) override;
+  void ReportQueriesPerCpuSec(const ScenarioResult& result) override;
 
  private:
   std::vector<std::unique_ptr<Reporter> > reporters_;
@@ -99,6 +103,7 @@
   void ReportTimes(const ScenarioResult& result) override;
   void ReportCpuUsage(const ScenarioResult& result) override;
   void ReportPollCount(const ScenarioResult& result) override;
+  void ReportQueriesPerCpuSec(const ScenarioResult& result) override;
 };
 
 /** Dumps the report to a JSON file. */
@@ -114,6 +119,7 @@
   void ReportTimes(const ScenarioResult& result) override;
   void ReportCpuUsage(const ScenarioResult& result) override;
   void ReportPollCount(const ScenarioResult& result) override;
+  void ReportQueriesPerCpuSec(const ScenarioResult& result) override;
 
   const string report_file_;
 };
@@ -130,6 +136,7 @@
   void ReportTimes(const ScenarioResult& result) override;
   void ReportCpuUsage(const ScenarioResult& result) override;
   void ReportPollCount(const ScenarioResult& result) override;
+  void ReportQueriesPerCpuSec(const ScenarioResult& result) override;
 
   std::unique_ptr<ReportQpsScenarioService::Stub> stub_;
 };
diff --git a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
index 5863926..137b33e 100644
--- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
@@ -23,6 +23,8 @@
 #include "test/cpp/qps/benchmark_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 namespace testing {
@@ -50,8 +52,8 @@
   client_config.mutable_security_params()->CopyFrom(security);
   server_config.mutable_security_params()->CopyFrom(security);
 
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
+  const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP,
+                                  BENCHMARK, -2, "", kInsecureCredentialsType);
 
   GetReporter()->ReportQPS(*result);
   GetReporter()->ReportLatency(*result);
@@ -61,7 +63,7 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
+  grpc::testing::InitTest(&argc, &argv, true);
 
   grpc::testing::RunSynchronousUnaryPingPong();
 
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index 4b699e0..df27a43 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -32,6 +32,7 @@
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/cpp/qps/usage_timer.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 namespace testing {
@@ -79,8 +80,11 @@
       return false;
     }
     payload->set_type(type);
-    std::unique_ptr<char[]> body(new char[size]());
-    payload->set_body(body.get(), size);
+    // Don't waste time creating a new payload of identical size.
+    if (payload->body().length() != (size_t)size) {
+      std::unique_ptr<char[]> body(new char[size]());
+      payload->set_body(body.get(), size);
+    }
     return true;
   }
 
@@ -89,12 +93,14 @@
   static std::shared_ptr<ServerCredentials> CreateServerCredentials(
       const ServerConfig& config) {
     if (config.has_security_params()) {
-      SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
-                                                          test_server1_cert};
-      SslServerCredentialsOptions ssl_opts;
-      ssl_opts.pem_root_certs = "";
-      ssl_opts.pem_key_cert_pairs.push_back(pkcp);
-      return SslServerCredentials(ssl_opts);
+      grpc::string type;
+      if (config.security_params().cred_type().empty()) {
+        type = kTlsCredentialsType;
+      } else {
+        type = config.security_params().cred_type();
+      }
+
+      return GetCredentialsProvider()->GetServerCredentials(type);
     } else {
       return InsecureServerCredentials();
     }
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index fd51d32..27010b7 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -27,9 +27,12 @@
 
 #include "test/cpp/qps/qps_worker.h"
 #include "test/cpp/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 DEFINE_int32(driver_port, 0, "Port for communication with driver");
 DEFINE_int32(server_port, 0, "Port for operation as a server");
+DEFINE_string(credential_type, grpc::testing::kInsecureCredentialsType,
+              "Credential type for communication with driver");
 
 static bool got_sigint = false;
 
@@ -39,7 +42,7 @@
 namespace testing {
 
 static void RunServer() {
-  QpsWorker worker(FLAGS_driver_port, FLAGS_server_port);
+  QpsWorker worker(FLAGS_driver_port, FLAGS_server_port, FLAGS_credential_type);
 
   while (!got_sigint && !worker.Done()) {
     gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD
new file mode 100644
index 0000000..512241e
--- /dev/null
+++ b/test/cpp/server/BUILD
@@ -0,0 +1,43 @@
+# 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_cc_test(
+    name = "server_builder_test",
+    srcs = ["server_builder_test.cc"],
+    deps = [
+        "//:grpc++",
+        "//src/proto/grpc/testing:echo_proto",
+        "//test/core/util:grpc_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+)
+
+grpc_cc_test(
+    name = "server_request_call_test",
+    srcs = ["server_request_call_test.cc"],
+    deps = [
+        "//:grpc++",
+        "//src/proto/grpc/testing:echo_proto",
+        "//test/core/util:grpc_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+)
diff --git a/test/cpp/server/server_request_call_test.cc b/test/cpp/server/server_request_call_test.cc
new file mode 100644
index 0000000..b0a2fa4
--- /dev/null
+++ b/test/cpp/server/server_request_call_test.cc
@@ -0,0 +1,163 @@
+/*
+ *
+ * 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 <thread>
+
+#include <grpc++/impl/codegen/config.h>
+
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+
+#include <grpc++/create_channel.h>
+#include <grpc++/security/credentials.h>
+
+#include <grpc/support/log.h>
+
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace {
+
+TEST(ServerRequestCallTest, ShortDeadlineDoesNotCauseOkayFalse) {
+  std::mutex mu;
+  bool shutting_down = false;
+
+  // grpc server config.
+  std::ostringstream s;
+  int p = grpc_pick_unused_port_or_die();
+  s << "[::1]:" << p;
+  const string address = s.str();
+  testing::EchoTestService::AsyncService service;
+  ServerBuilder builder;
+  builder.AddListeningPort(address, InsecureServerCredentials());
+  auto cq = builder.AddCompletionQueue();
+  builder.RegisterService(&service);
+  auto server = builder.BuildAndStart();
+
+  // server thread.
+  std::thread t([address, &service, &cq, &mu, &shutting_down] {
+    for (int n = 0; true; n++) {
+      ServerContext ctx;
+      testing::EchoRequest req;
+      ServerAsyncResponseWriter<testing::EchoResponse> responder(&ctx);
+
+      // if shutting down, don't enqueue a new request.
+      {
+        std::lock_guard<std::mutex> lock(mu);
+        if (!shutting_down) {
+          service.RequestEcho(&ctx, &req, &responder, cq.get(), cq.get(),
+                              (void*)1);
+        }
+      }
+
+      bool ok;
+      void* tag;
+      if (!cq->Next(&tag, &ok)) {
+        break;
+      }
+
+      EXPECT_EQ((void*)1, tag);
+      // If not shutting down, ok must be true for new requests.
+      {
+        std::lock_guard<std::mutex> lock(mu);
+        if (!shutting_down && !ok) {
+          gpr_log(GPR_INFO, "!ok on request %d", n);
+          abort();
+        }
+        if (shutting_down && !ok) {
+          // Failed connection due to shutdown, continue flushing the CQ.
+          continue;
+        }
+      }
+
+      // Send a simple response after a small delay that would ensure the client
+      // deadline is exceeded.
+      gpr_log(GPR_INFO, "Got request %d", n);
+      testing::EchoResponse response;
+      response.set_message("foobar");
+      // A bit of sleep to make sure the deadline elapses.
+      gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                                   gpr_time_from_millis(50, GPR_TIMESPAN)));
+      {
+        std::lock_guard<std::mutex> lock(mu);
+        if (shutting_down) {
+          gpr_log(GPR_INFO,
+                  "shut down while processing call, not calling Finish()");
+          // Continue flushing the CQ.
+          continue;
+        }
+        gpr_log(GPR_INFO, "Finishing request %d", n);
+        responder.Finish(response, grpc::Status::OK, (void*)2);
+        if (!cq->Next(&tag, &ok)) {
+          break;
+        }
+        EXPECT_EQ((void*)2, tag);
+      }
+    }
+  });
+
+  auto stub = testing::EchoTestService::NewStub(
+      CreateChannel(address, InsecureChannelCredentials()));
+
+  for (int i = 0; i < 100; i++) {
+    gpr_log(GPR_INFO, "Sending %d.", i);
+    testing::EchoRequest request;
+
+    /////////
+    // Comment out the following line to get ok=false due to invalid request.
+    // Otherwise, ok=false due to deadline being exceeded.
+    /////////
+    request.set_message("foobar");
+
+    // A simple request with a short deadline. The server will always exceed the
+    // deadline, whether due to the sleep or because the server was unable to
+    // even fetch the request from the CQ before the deadline elapsed.
+    testing::EchoResponse response;
+    ::grpc::ClientContext ctx;
+    ctx.set_fail_fast(false);
+    ctx.set_deadline(std::chrono::system_clock::now() +
+                     std::chrono::milliseconds(1));
+    grpc::Status status = stub->Echo(&ctx, request, &response);
+    EXPECT_EQ(DEADLINE_EXCEEDED, status.error_code());
+    gpr_log(GPR_INFO, "Success.");
+  }
+  gpr_log(GPR_INFO, "Done sending RPCs.");
+
+  // Shut down everything properly.
+  gpr_log(GPR_INFO, "Shutting down.");
+  {
+    std::lock_guard<std::mutex> lock(mu);
+    shutting_down = true;
+  }
+  server->Shutdown();
+  cq->Shutdown();
+  server->Wait();
+
+  t.join();
+}
+
+}  // namespace
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index 6db61ab..c9b0d6c 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -14,9 +14,15 @@
 
 licenses(["notice"])  # Apache v2
 
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_binary", "grpc_cc_test")
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 # The following builds a shared-object to confirm that grpc++_unsecure
 # builds properly. Build-only is sufficient here
@@ -24,6 +30,7 @@
     name = "testso.so",
     srcs = [],
     linkshared = 1,
+    linkopts = ['-Wl,--no-undefined'],
     deps = ["//:grpc++_unsecure"],
 )
 
@@ -126,19 +133,21 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "error_details_test",
     srcs = [
         "error_details_test.cc",
     ],
     deps = [
         "//:grpc++_error_details",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "grpc_cli",
     srcs = [
         "cli_call.cc",
@@ -160,7 +169,9 @@
     ],
     deps = [
         "//:grpc++",
-        "//external:gflags",
         "//src/proto/grpc/reflection/v1alpha:reflection_proto",
     ],
+    external_deps = [
+        "gflags",
+    ],
 )
diff --git a/test/cpp/util/byte_buffer_proto_helper.cc b/test/cpp/util/byte_buffer_proto_helper.cc
index 22dd074..bb5162f 100644
--- a/test/cpp/util/byte_buffer_proto_helper.cc
+++ b/test/cpp/util/byte_buffer_proto_helper.cc
@@ -36,8 +36,7 @@
     grpc::protobuf::Message* message) {
   grpc::string buf;
   message->SerializeToString(&buf);
-  grpc_slice s = grpc_slice_from_copied_string(buf.c_str());
-  Slice slice(s, Slice::STEAL_REF);
+  Slice slice(buf);
   return std::unique_ptr<ByteBuffer>(new ByteBuffer(&slice, 1));
 }
 
diff --git a/test/cpp/util/byte_buffer_test.cc b/test/cpp/util/byte_buffer_test.cc
index 6c077dd..cac01a7 100644
--- a/test/cpp/util/byte_buffer_test.cc
+++ b/test/cpp/util/byte_buffer_test.cc
@@ -34,33 +34,30 @@
 class ByteBufferTest : public ::testing::Test {};
 
 TEST_F(ByteBufferTest, CreateFromSingleSlice) {
-  grpc_slice hello = grpc_slice_from_copied_string(kContent1);
-  Slice s(hello, Slice::STEAL_REF);
+  Slice s(kContent1);
   ByteBuffer buffer(&s, 1);
+  EXPECT_EQ(strlen(kContent1), buffer.Length());
 }
 
 TEST_F(ByteBufferTest, CreateFromVector) {
-  grpc_slice hello = grpc_slice_from_copied_string(kContent1);
-  grpc_slice world = grpc_slice_from_copied_string(kContent2);
   std::vector<Slice> slices;
-  slices.push_back(Slice(hello, Slice::STEAL_REF));
-  slices.push_back(Slice(world, Slice::STEAL_REF));
+  slices.emplace_back(kContent1);
+  slices.emplace_back(kContent2);
   ByteBuffer buffer(&slices[0], 2);
+  EXPECT_EQ(strlen(kContent1) + strlen(kContent2), buffer.Length());
 }
 
 TEST_F(ByteBufferTest, Clear) {
-  grpc_slice hello = grpc_slice_from_copied_string(kContent1);
-  Slice s(hello, Slice::STEAL_REF);
+  Slice s(kContent1);
   ByteBuffer buffer(&s, 1);
   buffer.Clear();
+  EXPECT_EQ(static_cast<size_t>(0), buffer.Length());
 }
 
 TEST_F(ByteBufferTest, Length) {
-  grpc_slice hello = grpc_slice_from_copied_string(kContent1);
-  grpc_slice world = grpc_slice_from_copied_string(kContent2);
   std::vector<Slice> slices;
-  slices.push_back(Slice(hello, Slice::STEAL_REF));
-  slices.push_back(Slice(world, Slice::STEAL_REF));
+  slices.emplace_back(kContent1);
+  slices.emplace_back(kContent2);
   ByteBuffer buffer(&slices[0], 2);
   EXPECT_EQ(strlen(kContent1) + strlen(kContent2), buffer.Length());
 }
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index fb6d76b..c3220ef 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -119,8 +119,7 @@
 }
 
 void CliCall::WriteAndWait(const grpc::string& request) {
-  grpc_slice s = grpc_slice_from_copied_string(request.c_str());
-  grpc::Slice req_slice(s, grpc::Slice::STEAL_REF);
+  grpc::Slice req_slice(request);
   grpc::ByteBuffer send_buffer(&req_slice, 1);
 
   gpr_mu_lock(&write_mu_);
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index 68c6fe4..34b6d60 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -51,29 +51,31 @@
 
 }  // namespace
 
-// When ssl is enabled, if server is empty, override_hostname is used to
+// When cred_type is 'ssl', if server is empty, override_hostname is used to
 // create channel. Otherwise, connect to server and override hostname if
 // override_hostname is provided.
-// When ssl is not enabled, override_hostname is ignored.
+// When cred_type is not 'ssl', override_hostname is ignored.
 // Set use_prod_root to true to use the SSL root for connecting to google.
 // In this case, path to the roots pem file must be set via environment variable
 // GRPC_DEFAULT_SSL_ROOTS_FILE_PATH.
 // Otherwise, root for test SSL cert will be used.
-// creds will be used to create a channel when enable_ssl is true.
+// creds will be used to create a channel when cred_type is 'ssl'.
 // Use examples:
 //   CreateTestChannel(
-//       "1.1.1.1:12345", "override.hostname.com", true, false, creds);
-//   CreateTestChannel("test.google.com:443", "", true, true, creds);
+//       "1.1.1.1:12345", "ssl", "override.hostname.com", false, creds);
+//   CreateTestChannel("test.google.com:443", "ssl", "", true, creds);
 //   same as above
-//   CreateTestChannel("", "test.google.com:443", true, true, creds);
+//   CreateTestChannel("", "ssl", "test.google.com:443", true, creds);
 std::shared_ptr<Channel> CreateTestChannel(
-    const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    const grpc::string& server, const grpc::string& cred_type,
+    const grpc::string& override_hostname, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args) {
   ChannelArguments channel_args(args);
   std::shared_ptr<ChannelCredentials> channel_creds;
-  if (enable_ssl) {
+  if (cred_type.empty()) {
+    return CreateChannel(server, InsecureChannelCredentials());
+  } else if (cred_type == testing::kTlsCredentialsType) {  // cred_type == "ssl"
     if (use_prod_roots) {
       gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType);
       channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
@@ -95,13 +97,31 @@
     }
     return CreateCustomChannel(connect_to, channel_creds, channel_args);
   } else {
-    return CreateChannel(server, InsecureChannelCredentials());
+    channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
+        cred_type, &channel_args);
+    GPR_ASSERT(channel_creds != nullptr);
+
+    return CreateChannel(server, channel_creds);
   }
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots,
+    const std::shared_ptr<CallCredentials>& creds,
+    const ChannelArguments& args) {
+  grpc::string type;
+  if (enable_ssl) {
+    type = testing::kTlsCredentialsType;
+  }
+
+  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,
     const std::shared_ptr<CallCredentials>& creds) {
   return CreateTestChannel(server, override_hostname, enable_ssl,
                            use_prod_roots, creds, ChannelArguments());
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index 9b4b091..e2ca8f9 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -45,6 +45,12 @@
     const ChannelArguments& args);
 
 std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, const grpc::string& cred_type,
+    const grpc::string& override_hostname, bool use_prod_roots,
+    const std::shared_ptr<CallCredentials>& creds,
+    const ChannelArguments& args);
+
+std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& credential_type,
     const std::shared_ptr<CallCredentials>& creds);
 
diff --git a/test/cpp/util/slice_test.cc b/test/cpp/util/slice_test.cc
index 0f80003..9e3329f 100644
--- a/test/cpp/util/slice_test.cc
+++ b/test/cpp/util/slice_test.cc
@@ -28,6 +28,9 @@
 
 class SliceTest : public ::testing::Test {
  protected:
+  void CheckSliceSize(const Slice& s, const grpc::string& content) {
+    EXPECT_EQ(content.size(), s.size());
+  }
   void CheckSlice(const Slice& s, const grpc::string& content) {
     EXPECT_EQ(content.size(), s.size());
     EXPECT_EQ(content,
@@ -35,6 +38,31 @@
   }
 };
 
+TEST_F(SliceTest, Empty) {
+  Slice empty_slice;
+  CheckSlice(empty_slice, "");
+}
+
+TEST_F(SliceTest, Sized) {
+  Slice sized_slice(strlen(kContent));
+  CheckSliceSize(sized_slice, kContent);
+}
+
+TEST_F(SliceTest, String) {
+  Slice spp(kContent);
+  CheckSlice(spp, kContent);
+}
+
+TEST_F(SliceTest, Buf) {
+  Slice spp(kContent, strlen(kContent));
+  CheckSlice(spp, kContent);
+}
+
+TEST_F(SliceTest, StaticBuf) {
+  Slice spp(kContent, strlen(kContent), Slice::STATIC_SLICE);
+  CheckSlice(spp, kContent);
+}
+
 TEST_F(SliceTest, Steal) {
   grpc_slice s = grpc_slice_from_copied_string(kContent);
   Slice spp(s, Slice::STEAL_REF);
@@ -48,11 +76,6 @@
   CheckSlice(spp, kContent);
 }
 
-TEST_F(SliceTest, Empty) {
-  Slice empty_slice;
-  CheckSlice(empty_slice, "");
-}
-
 TEST_F(SliceTest, Cslice) {
   grpc_slice s = grpc_slice_from_copied_string(kContent);
   Slice spp(s, Slice::STEAL_REF);
diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh
index 3a18255..3c9235b 100755
--- a/tools/distrib/pylint_code.sh
+++ b/tools/distrib/pylint_code.sh
@@ -22,6 +22,7 @@
     'src/python/grpcio/grpc'
     'src/python/grpcio_health_checking/grpc_health'
     'src/python/grpcio_reflection/grpc_reflection'
+    'src/python/grpcio_testing/grpc_testing'
 )
 
 VIRTUALENV=python_pylint_venv
diff --git a/tools/distrib/python/grpcio_tools/setup.py b/tools/distrib/python/grpcio_tools/setup.py
index bc24e4c..5c0329b 100644
--- a/tools/distrib/python/grpcio_tools/setup.py
+++ b/tools/distrib/python/grpcio_tools/setup.py
@@ -37,6 +37,18 @@
 import protoc_lib_deps
 import grpc_version
 
+CLASSIFIERS = [
+    'Development Status :: 5 - Production/Stable',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.4',
+    'Programming Language :: Python :: 3.5',
+    'Programming Language :: Python :: 3.6',
+    'License :: OSI Approved :: Apache Software License',
+],
+
 PY3 = sys.version_info.major == 3
 
 # Environment variable to determine whether or not the Cython extension should
@@ -62,9 +74,9 @@
       # envvars) without adding yet more GRPC-specific envvars.
       # See https://sourceforge.net/p/mingw-w64/bugs/363/
       if '32' in platform.architecture()[0]:
-        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
+        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s -D_hypot=hypot'
       else:
-        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
+        EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64 -D_hypot=hypot'
     else:
       # We need to statically link the C++ Runtime, only the C runtime is
       # available dynamically
@@ -193,6 +205,7 @@
   author_email='grpc-io@googlegroups.com',
   url='https://grpc.io',
   license='Apache License 2.0',
+  classifiers=CLASSIFIERS,
   ext_modules=extension_modules(),
   packages=setuptools.find_packages('.'),
   install_requires=[
diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh
index 4f75163..dbb6b5c 100755
--- a/tools/distrib/yapf_code.sh
+++ b/tools/distrib/yapf_code.sh
@@ -25,6 +25,7 @@
     'grpcio/grpc_*.py'
     'grpcio_health_checking/grpc_*.py'
     'grpcio_reflection/grpc_*.py'
+    'grpcio_testing/grpc_*.py'
     'grpcio_tests/grpc_*.py'
 )
 
diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
index c667655..0251b2b 100644
--- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
+++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
@@ -49,19 +49,7 @@
 # Install Node dependencies
 RUN touch .profile
 RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
-RUN /bin/bash -l -c "nvm install 4 && npm install -g node-pre-gyp"
-
-##################
-# Python dependencies
-
-RUN apt-get update && apt-get install -y \
-    python-all-dev \
-    python3-all-dev \
-    python-pip
-
-RUN pip install pip --upgrade
-RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0
+RUN /bin/bash -l -c "nvm install 8 && npm install -g node-pre-gyp"
 
 
 ##################
diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
index 79f2301..2d179c8 100644
--- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
+++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
@@ -49,19 +49,7 @@
 # Install Node dependencies
 RUN touch .profile
 RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
-RUN /bin/bash -l -c "nvm install 4 && npm install -g node-pre-gyp"
-
-##################
-# Python dependencies
-
-RUN apt-get update && apt-get install -y \
-    python-all-dev \
-    python3-all-dev \
-    python-pip
-
-RUN pip install pip --upgrade
-RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0
+RUN /bin/bash -l -c "nvm install 8 && npm install -g node-pre-gyp"
 
 
 ##################
diff --git a/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
index 35998a3..519cdbf 100644
--- a/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
@@ -55,22 +55,24 @@
   apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && \
   gcloud config set component_manager/disable_update_check true
 
-# Download and install grpc-java
+# Install Android SDK
 WORKDIR /
-RUN git clone https://github.com/grpc/grpc-java.git
-WORKDIR /grpc-java
-RUN ./gradlew install
+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"
 
-# Setup the Android SDK licenses
-ENV ANDROID_HOME "/grpc-java/android-interop-testing/.android"
-RUN mkdir -p "${ANDROID_HOME}/licenses"
-RUN echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
-RUN echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "${ANDROID_HOME}/licenses/android-sdk-preview-license"
-
-# Build the Android interop apks
-WORKDIR /grpc-java/android-interop-testing
-RUN ../gradlew assembleDebug
-RUN ../gradlew assembleDebugAndroidTest
+# Reset the working directory
+WORKDIR /
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 23746de..589ef1c 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -871,6 +871,12 @@
 include/grpc++/support/stub_options.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/time.h \
+include/grpc/byte_buffer.h \
+include/grpc/byte_buffer_reader.h \
+include/grpc/compression.h \
+include/grpc/grpc.h \
+include/grpc/grpc_posix.h \
+include/grpc/grpc_security_constants.h \
 include/grpc/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
@@ -889,7 +895,38 @@
 include/grpc/impl/codegen/sync.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/sync_windows.h \
+include/grpc/load_reporting.h \
+include/grpc/slice.h \
+include/grpc/slice_buffer.h \
+include/grpc/status.h \
+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/avl.h \
+include/grpc/support/cmdline.h \
+include/grpc/support/cpu.h \
+include/grpc/support/histogram.h \
+include/grpc/support/host_port.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/subprocess.h \
+include/grpc/support/sync.h \
+include/grpc/support/sync_generic.h \
+include/grpc/support/sync_posix.h \
+include/grpc/support/sync_windows.h \
+include/grpc/support/thd.h \
+include/grpc/support/time.h \
+include/grpc/support/tls.h \
+include/grpc/support/tls_gcc.h \
+include/grpc/support/tls_msvc.h \
+include/grpc/support/tls_pthread.h \
+include/grpc/support/useful.h \
+include/grpc/support/workaround_list.h
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 52e722f..3352431 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -872,6 +872,12 @@
 include/grpc++/support/stub_options.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/time.h \
+include/grpc/byte_buffer.h \
+include/grpc/byte_buffer_reader.h \
+include/grpc/compression.h \
+include/grpc/grpc.h \
+include/grpc/grpc_posix.h \
+include/grpc/grpc_security_constants.h \
 include/grpc/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
@@ -891,6 +897,169 @@
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
+include/grpc/slice.h \
+include/grpc/slice_buffer.h \
+include/grpc/status.h \
+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/avl.h \
+include/grpc/support/cmdline.h \
+include/grpc/support/cpu.h \
+include/grpc/support/histogram.h \
+include/grpc/support/host_port.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/subprocess.h \
+include/grpc/support/sync.h \
+include/grpc/support/sync_generic.h \
+include/grpc/support/sync_posix.h \
+include/grpc/support/sync_windows.h \
+include/grpc/support/thd.h \
+include/grpc/support/time.h \
+include/grpc/support/tls.h \
+include/grpc/support/tls_gcc.h \
+include/grpc/support/tls_msvc.h \
+include/grpc/support/tls_pthread.h \
+include/grpc/support/useful.h \
+include/grpc/support/workaround_list.h \
+src/core/ext/transport/inproc/inproc_transport.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/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/compression/algorithm_metadata.h \
+src/core/lib/compression/message_compress.h \
+src/core/lib/compression/stream_compression.h \
+src/core/lib/debug/trace.h \
+src/core/lib/http/format_request.h \
+src/core/lib/http/httpcli.h \
+src/core/lib/http/parser.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_epoll_limited_pollers_linux.h \
+src/core/lib/iomgr/ev_epoll_thread_pool_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/iocp_windows.h \
+src/core/lib/iomgr/iomgr.h \
+src/core/lib/iomgr/iomgr_internal.h \
+src/core/lib/iomgr/iomgr_posix.h \
+src/core/lib/iomgr/iomgr_uv.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_set.h \
+src/core/lib/iomgr/pollset_set_windows.h \
+src/core/lib/iomgr/pollset_uv.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/resource_quota.h \
+src/core/lib/iomgr/sockaddr.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_posix.h \
+src/core/lib/iomgr/tcp_server.h \
+src/core/lib/iomgr/tcp_server_utils_posix.h \
+src/core/lib/iomgr/tcp_uv.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_generic.h \
+src/core/lib/iomgr/timer_heap.h \
+src/core/lib/iomgr/timer_manager.h \
+src/core/lib/iomgr/timer_uv.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/profiling/timers.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/support/arena.h \
+src/core/lib/support/atomic.h \
+src/core/lib/support/atomic_with_atm.h \
+src/core/lib/support/atomic_with_std.h \
+src/core/lib/support/backoff.h \
+src/core/lib/support/block_annotate.h \
+src/core/lib/support/env.h \
+src/core/lib/support/memory.h \
+src/core/lib/support/mpscq.h \
+src/core/lib/support/murmur_hash.h \
+src/core/lib/support/spinlock.h \
+src/core/lib/support/stack_lockfree.h \
+src/core/lib/support/string.h \
+src/core/lib/support/string_windows.h \
+src/core/lib/support/thd_internal.h \
+src/core/lib/support/time_precise.h \
+src/core/lib/support/tmpfile.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/timeout_encoding.h \
+src/core/lib/transport/transport.h \
+src/core/lib/transport/transport_impl.h \
 src/cpp/README.md \
 src/cpp/client/channel_cc.cc \
 src/cpp/client/client_context.cc \
@@ -945,11 +1114,8 @@
 src/cpp/util/string_ref.cc \
 src/cpp/util/time_cc.cc \
 third_party/nanopb/pb.h \
-third_party/nanopb/pb_common.c \
 third_party/nanopb/pb_common.h \
-third_party/nanopb/pb_decode.c \
 third_party/nanopb/pb_decode.h \
-third_party/nanopb/pb_encode.c \
 third_party/nanopb/pb_encode.h
 
 # This tag can be used to specify the character encoding of the source files
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 766c20f..9951edc 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1014,6 +1014,7 @@
 src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
 src/core/ext/transport/chttp2/transport/chttp2_transport.c \
 src/core/ext/transport/chttp2/transport/chttp2_transport.h \
+src/core/ext/transport/chttp2/transport/flow_control.c \
 src/core/ext/transport/chttp2/transport/frame.h \
 src/core/ext/transport/chttp2/transport/frame_data.c \
 src/core/ext/transport/chttp2/transport/frame_data.h \
@@ -1047,6 +1048,9 @@
 src/core/ext/transport/chttp2/transport/varint.c \
 src/core/ext/transport/chttp2/transport/varint.h \
 src/core/ext/transport/chttp2/transport/writing.c \
+src/core/ext/transport/inproc/inproc_plugin.c \
+src/core/ext/transport/inproc/inproc_transport.c \
+src/core/ext/transport/inproc/inproc_transport.h \
 src/core/lib/README.md \
 src/core/lib/channel/README.md \
 src/core/lib/channel/channel_args.c \
@@ -1068,6 +1072,8 @@
 src/core/lib/compression/compression.c \
 src/core/lib/compression/message_compress.c \
 src/core/lib/compression/message_compress.h \
+src/core/lib/compression/stream_compression.c \
+src/core/lib/compression/stream_compression.h \
 src/core/lib/debug/trace.c \
 src/core/lib/debug/trace.h \
 src/core/lib/http/format_request.c \
@@ -1118,6 +1124,7 @@
 src/core/lib/iomgr/iomgr_posix.c \
 src/core/lib/iomgr/iomgr_posix.h \
 src/core/lib/iomgr/iomgr_uv.c \
+src/core/lib/iomgr/iomgr_uv.h \
 src/core/lib/iomgr/iomgr_windows.c \
 src/core/lib/iomgr/is_epollexclusive_available.c \
 src/core/lib/iomgr/is_epollexclusive_available.h \
@@ -1125,6 +1132,7 @@
 src/core/lib/iomgr/load_file.h \
 src/core/lib/iomgr/lockfree_event.c \
 src/core/lib/iomgr/lockfree_event.h \
+src/core/lib/iomgr/nameser.h \
 src/core/lib/iomgr/network_status_tracker.c \
 src/core/lib/iomgr/network_status_tracker.h \
 src/core/lib/iomgr/polling_entity.c \
@@ -1399,6 +1407,8 @@
 src/core/tsi/README.md \
 src/core/tsi/fake_transport_security.c \
 src/core/tsi/fake_transport_security.h \
+src/core/tsi/gts_transport_security.c \
+src/core/tsi/gts_transport_security.h \
 src/core/tsi/ssl_transport_security.c \
 src/core/tsi/ssl_transport_security.h \
 src/core/tsi/ssl_types.h \
@@ -1407,13 +1417,9 @@
 src/core/tsi/transport_security_adapter.c \
 src/core/tsi/transport_security_adapter.h \
 src/core/tsi/transport_security_interface.h \
-third_party/nanopb/pb.h \
 third_party/nanopb/pb_common.c \
-third_party/nanopb/pb_common.h \
 third_party/nanopb/pb_decode.c \
-third_party/nanopb/pb_decode.h \
-third_party/nanopb/pb_encode.c \
-third_party/nanopb/pb_encode.h
+third_party/nanopb/pb_encode.c
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/tools/internal_ci/helper_scripts/gen_report_index.sh b/tools/internal_ci/helper_scripts/gen_report_index.sh
new file mode 100755
index 0000000..0af89c3
--- /dev/null
+++ b/tools/internal_ci/helper_scripts/gen_report_index.sh
@@ -0,0 +1,35 @@
+#!/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://kokoro.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_interop_rc b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
index cc956b8..859ce62 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_interop_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
@@ -26,3 +26,8 @@
 # Set up gRPC-Go and gRPC-Java to test
 git clone --recursive https://github.com/grpc/grpc-go ./../grpc-go
 git clone --recursive https://github.com/grpc/grpc-java ./../grpc-java
+
+# Download json file.
+mkdir ~/service_account
+gsutil cp gs://grpc-testing-secrets/interop/service_account/GrpcTesting-726eb1347f15.json ~/service_account
+export GOOGLE_APPLICATION_CREDENTIALS=~/service_account/GrpcTesting-726eb1347f15.json
diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
index 7b7db19..049db33 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_linux_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
@@ -15,6 +15,8 @@
 
 # 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_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
index 57463e6..00105d4 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
@@ -15,6 +15,8 @@
 
 # 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
@@ -25,6 +27,11 @@
 # show current limits
 ulimit -a
 
+# Add GCP credentials for BQ access
+# pip does not install google-api-python-client properly, so use easy_install
+sudo easy_install --upgrade google-api-python-client
+export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json
+gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS
 
 # required to build protobuf
 brew install gflags
diff --git a/tools/internal_ci/helper_scripts/prepare_build_windows.bat b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
new file mode 100644
index 0000000..69e087e
--- /dev/null
+++ b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
@@ -0,0 +1,31 @@
+@rem Copyright 2017 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 make sure msys binaries are preferred over cygwin binaries
+@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 Update DNS settings to:
+@rem 1. allow resolving metadata.google.internal hostname
+@rem 2. make fetching default GCE credential by oauth2client work
+netsh interface ip set dns "Local Area Connection 8" static 169.254.169.254 primary
+netsh interface ip add dnsservers "Local Area Connection 8" 8.8.8.8 index=2
+netsh interface ip add dnsservers "Local Area Connection 8" 8.8.4.4 index=3
+
+@rem Needed for big_query_utils
+python -m pip install google-api-python-client
+
+git submodule update --init
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
similarity index 85%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
index 8bcc668..4a0badf 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux corelang dbg --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
similarity index 85%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
index 8bcc668..a2cfe02 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux corelang opt --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_basictests_multilang.cfg
similarity index 85%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/linux/grpc_basictests_multilang.cfg
index 8bcc668..4433d14 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_multilang.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux multilang --inner_jobs 16 -j 2 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/linux/grpc_build_artifacts.cfg b/tools/internal_ci/linux/grpc_build_artifacts.cfg
index eb37b5b..88fc6b7 100644
--- a/tools/internal_ci/linux/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/linux/grpc_build_artifacts.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
     regex: "github/grpc/artifacts/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_build_artifacts.sh b/tools/internal_ci/linux/grpc_build_artifacts.sh
index bc29014..985243e 100755
--- a/tools/internal_ci/linux/grpc_build_artifacts.sh
+++ b/tools/internal_ci/linux/grpc_build_artifacts.sh
@@ -20,9 +20,10 @@
 
 source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 
-# TODO(jtattermusch): install ruby on the internal_ci worker
-gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
-# TODO(jtattermusch): grep works around https://github.com/rvm/rvm/issues/4068
-curl -sSL https://get.rvm.io | grep -v __rvm_print_headline | bash -s stable --ruby
+set +ex
+[[ -s /etc/profile.d/rvm.sh ]] && . /etc/profile.d/rvm.sh
+set -e  # rvm commands are very verbose
+rvm --default use ruby-2.4.1
+set -ex
 
-tools/run_tests/task_runner.py -f artifact linux
+tools/run_tests/task_runner.py -f artifact linux -j 6
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
index 0aadb56..dc21142 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
@@ -20,7 +20,7 @@
 timeout_mins: 480
 action {
   define_artifacts {
-    regex: "**/report.xml",
+    regex: "**/report.xml"
     regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
index 29c5c63..ec738fc 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
@@ -20,7 +20,7 @@
 timeout_mins: 480
 action {
   define_artifacts {
-    regex: "**/report.xml",
+    regex: "**/report.xml"
     regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/windows/grpc_master.cfg b/tools/internal_ci/linux/grpc_interop_matrix.cfg
similarity index 77%
rename from tools/internal_ci/windows/grpc_master.cfg
rename to tools/internal_ci/linux/grpc_interop_matrix.cfg
index 80abea6..a7fd479 100644
--- a/tools/internal_ci/windows/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_interop_matrix.cfg
@@ -15,10 +15,12 @@
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/windows/grpc_master.bat"
-timeout_mins: 360
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_matrix.sh"
+# grpc_interop tests can take 1 hours to complete.
+timeout_mins: 60
 action {
   define_artifacts {
-    regex: "**/*sponge_log.xml"
+    regex: "**/sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/windows/grpc_master.cfg b/tools/internal_ci/linux/grpc_interop_matrix.sh
old mode 100644
new mode 100755
similarity index 66%
copy from tools/internal_ci/windows/grpc_master.cfg
copy to tools/internal_ci/linux/grpc_interop_matrix.sh
index 80abea6..e199d48
--- a/tools/internal_ci/windows/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_interop_matrix.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
 # Copyright 2017 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Config file for the internal CI (in protobuf text format)
+set -ex
 
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/windows/grpc_master.bat"
-timeout_mins: 360
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.xml"
-  }
-}
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+tools/interop_matrix/run_interop_matrix_tests.py --language=all --release=all --report_file=sponge_log.xml $@
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
index 0c31b49..c613f66 100644
--- a/tools/internal_ci/linux/grpc_interop_tocloud.cfg
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
@@ -21,5 +21,6 @@
 action {
   define_artifacts {
     regex: "**/sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.cfg b/tools/internal_ci/linux/grpc_interop_toprod.cfg
index 18978b8..903480a 100644
--- a/tools/internal_ci/linux/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/grpc_interop_toprod.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.sh b/tools/internal_ci/linux/grpc_interop_toprod.sh
old mode 100644
new mode 100755
diff --git a/tools/internal_ci/linux/grpc_portability.cfg b/tools/internal_ci/linux/grpc_portability.cfg
index c5bfd3b..8c120be 100644
--- a/tools/internal_ci/linux/grpc_portability.cfg
+++ b/tools/internal_ci/linux/grpc_portability.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.cfg b/tools/internal_ci/linux/grpc_portability_build_only.cfg
index fce914c..501223c 100644
--- a/tools/internal_ci/linux/grpc_portability_build_only.cfg
+++ b/tools/internal_ci/linux/grpc_portability_build_only.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
index 6c76a92..b20d2ff 100644
--- a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_sanity.cfg b/tools/internal_ci/linux/grpc_sanity.cfg
index 8dfeda0..24e7984 100644
--- a/tools/internal_ci/linux/grpc_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_sanity.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
similarity index 87%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
index 8bcc668..dcc6265 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux corelang dbg --inner_jobs 16 -j 1 --internal_ci"
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
similarity index 87%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
index 8bcc668..f60beaf 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux corelang opt --inner_jobs 16 -j 1 --internal_ci"
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
similarity index 88%
rename from tools/internal_ci/linux/grpc_master.cfg
rename to tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
index 8bcc668..7c16cf6 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
@@ -20,10 +20,11 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests linux multilang --inner_jobs 16 -j 2 --internal_ci"
 }
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
index c4beaac..06a4372 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
index 0197966..f875327 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
index 243eb99..6658a80 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
index 24c7bf8..957a91e 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
index f12366c..dbbfce9 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
index ca807ae..fb0cefa 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
index 98eb4d0..649d93d 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
index e47762c..d5ba203 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
index c3803af..67d4356 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
index 831cfb5..c162d1d 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
index c332443..29f1fce 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
index 92cd93f..331f73b 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
@@ -21,6 +21,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/macos/grpc_basictests.cfg
similarity index 73%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/macos/grpc_basictests.cfg
index 8bcc668..e10c2e3 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/macos/grpc_basictests.cfg
@@ -15,15 +15,17 @@
 # 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"
+build_file: "grpc/tools/internal_ci/macos/grpc_run_tests_matrix.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.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 --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests macos --internal_ci -j 2 --inner_jobs 4 --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/macos/grpc_build_artifacts.cfg b/tools/internal_ci/macos/grpc_build_artifacts.cfg
index 1999380..4da61fa 100644
--- a/tools/internal_ci/macos/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/macos/grpc_build_artifacts.cfg
@@ -16,10 +16,12 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/macos/grpc_build_artifacts.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json"
 timeout_mins: 120
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
     regex: "github/grpc/artifacts/**"
   }
 }
diff --git a/tools/internal_ci/macos/grpc_interop.cfg b/tools/internal_ci/macos/grpc_interop.cfg
index 25bac2f..b4b1b15 100644
--- a/tools/internal_ci/macos/grpc_interop.cfg
+++ b/tools/internal_ci/macos/grpc_interop.cfg
@@ -16,10 +16,11 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/macos/grpc_interop.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json"
 timeout_mins: 240
 action {
   define_artifacts {
-    regex: "**/*sponge_log.xml",
+    regex: "**/*sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/macos/grpc_master.sh b/tools/internal_ci/macos/grpc_run_tests_matrix.sh
similarity index 88%
rename from tools/internal_ci/macos/grpc_master.sh
rename to tools/internal_ci/macos/grpc_run_tests_matrix.sh
index c64666b..9a43e48 100755
--- a/tools/internal_ci/macos/grpc_master.sh
+++ b/tools/internal_ci/macos/grpc_run_tests_matrix.sh
@@ -20,7 +20,7 @@
 
 source tools/internal_ci/helper_scripts/prepare_build_macos_rc
 
-tools/run_tests/run_tests_matrix.py -f basictests macos --internal_ci -j 2 --inner_jobs 4 || FAILED="true"
+tools/run_tests/run_tests_matrix.py $RUN_TESTS_FLAGS || FAILED="true"
 
 # kill port_server.py to prevent the build from hanging
 ps aux | grep port_server\\.py | awk '{print $2}' | xargs kill -9
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/macos/pull_request/grpc_basictests.cfg
similarity index 75%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/macos/pull_request/grpc_basictests.cfg
index 8bcc668..e297091 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/macos/pull_request/grpc_basictests.cfg
@@ -15,15 +15,17 @@
 # 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"
+build_file: "grpc/tools/internal_ci/macos/grpc_run_tests_matrix.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.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 --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests macos --internal_ci -j 2 --inner_jobs 4"
 }
diff --git a/tools/internal_ci/macos/grpc_master.cfg b/tools/internal_ci/macos/pull_request/grpc_interop.cfg
similarity index 79%
rename from tools/internal_ci/macos/grpc_master.cfg
rename to tools/internal_ci/macos/pull_request/grpc_interop.cfg
index 1c34979..b4b1b15 100644
--- a/tools/internal_ci/macos/grpc_master.cfg
+++ b/tools/internal_ci/macos/pull_request/grpc_interop.cfg
@@ -15,10 +15,12 @@
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/macos/grpc_master.sh"
+build_file: "grpc/tools/internal_ci/macos/grpc_interop.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json"
 timeout_mins: 240
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/windows/grpc_basictests.cfg
similarity index 77%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/windows/grpc_basictests.cfg
index 8bcc668..396d29e 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/windows/grpc_basictests.cfg
@@ -15,15 +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: 240
+build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
+timeout_mins: 360
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests windows -j 1 --inner_jobs 8 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/windows/grpc_build_artifacts.bat b/tools/internal_ci/windows/grpc_build_artifacts.bat
index d5ade5a..29c876d 100644
--- a/tools/internal_ci/windows/grpc_build_artifacts.bat
+++ b/tools/internal_ci/windows/grpc_build_artifacts.bat
@@ -12,21 +12,19 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem Move python installation from _32bit to _32bits where they are expected python artifact builder
+@rem Move python installation from _32bit to _32bits where they are expected by python artifact builder
 @rem TODO(jtattermusch): get rid of this hack
 rename C:\Python27_32bit Python27_32bits
 rename C:\Python34_32bit Python34_32bits
 rename C:\Python35_32bit Python35_32bits
 rename C:\Python36_32bit Python36_32bits
 
-@rem make sure msys binaries are preferred over cygwin binaries
-@rem set path to python 2.7
-set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
+pacman -S --noconfirm mingw64/mingw-w64-x86_64-gcc mingw32/mingw-w64-i686-gcc
 
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
-git submodule update --init
+call tools/internal_ci/helper_scripts/prepare_build_windows.bat
 
 python tools/run_tests/task_runner.py -f artifact windows || goto :error
 goto :EOF
diff --git a/tools/internal_ci/windows/grpc_build_artifacts.cfg b/tools/internal_ci/windows/grpc_build_artifacts.cfg
index da359ca..38b0abd 100644
--- a/tools/internal_ci/windows/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/windows/grpc_build_artifacts.cfg
@@ -20,6 +20,7 @@
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
     regex: "github/grpc/artifacts/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/windows/grpc_portability.cfg
similarity index 80%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/windows/grpc_portability.cfg
index 8bcc668..c395cb4 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/windows/grpc_portability.cfg
@@ -15,15 +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: 240
+build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
+timeout_mins: 360
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f portability windows -j 1 --inner_jobs 8 --internal_ci"
 }
diff --git a/tools/internal_ci/windows/grpc_portability_master.bat b/tools/internal_ci/windows/grpc_portability_master.bat
deleted file mode 100644
index cb6b1fe..0000000
--- a/tools/internal_ci/windows/grpc_portability_master.bat
+++ /dev/null
@@ -1,28 +0,0 @@
-@rem Copyright 2017 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 make sure msys binaries are preferred over cygwin binaries
-@rem set path to python 2.7
-set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
-
-@rem enter repo root
-cd /d %~dp0\..\..\..
-
-git submodule update --init
-
-python tools/run_tests/run_tests_matrix.py -f portability windows -j 1 --inner_jobs 8 --internal_ci || goto :error
-goto :EOF
-
-:error
-exit /b %errorlevel%
diff --git a/tools/internal_ci/windows/grpc_portability_master.cfg b/tools/internal_ci/windows/grpc_portability_master.cfg
index cb48d35..c395cb4 100644
--- a/tools/internal_ci/windows/grpc_portability_master.cfg
+++ b/tools/internal_ci/windows/grpc_portability_master.cfg
@@ -15,10 +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/windows/grpc_portability_master.bat"
+build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
 timeout_mins: 360
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
+
+env_vars {
+  key: "RUN_TESTS_FLAGS"
+  value: "-f portability windows -j 1 --inner_jobs 8 --internal_ci"
+}
diff --git a/tools/internal_ci/windows/grpc_master.bat b/tools/internal_ci/windows/grpc_run_tests_matrix.bat
similarity index 70%
rename from tools/internal_ci/windows/grpc_master.bat
rename to tools/internal_ci/windows/grpc_run_tests_matrix.bat
index 3984b81..08d834f 100644
--- a/tools/internal_ci/windows/grpc_master.bat
+++ b/tools/internal_ci/windows/grpc_run_tests_matrix.bat
@@ -12,16 +12,12 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem make sure msys binaries are preferred over cygwin binaries
-@rem set path to python 2.7
-set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
-
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
-git submodule update --init
+call tools/internal_ci/helper_scripts/prepare_build_windows.bat
 
-python tools/run_tests/run_tests_matrix.py -f basictests windows -j 1 --inner_jobs 8 --internal_ci || goto :error
+python tools/run_tests/run_tests_matrix.py %RUN_TESTS_FLAGS% || goto :error
 goto :EOF
 
 :error
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg
similarity index 80%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/windows/pull_request/grpc_basictests.cfg
index 8bcc668..a116738 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg
@@ -15,15 +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: 240
+build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
+timeout_mins: 360
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f basictests windows -j 1 --inner_jobs 8 --internal_ci"
 }
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/windows/pull_request/grpc_portability.cfg
similarity index 80%
copy from tools/internal_ci/linux/grpc_master.cfg
copy to tools/internal_ci/windows/pull_request/grpc_portability.cfg
index 8bcc668..c395cb4 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_portability.cfg
@@ -15,15 +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: 240
+build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
+timeout_mins: 360
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
+  value: "-f portability windows -j 1 --inner_jobs 8 --internal_ci"
 }
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 34becf9..4d1b5f0 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -19,17 +19,38 @@
   return {
       'go': 'git@github.com:grpc/grpc-go.git',
       'java': 'git@github.com:grpc/grpc-java.git',
+      # all other languages use the grpc.git repo.
   }.get(lang, 'git@github.com:grpc/grpc.git')
 
 # Dictionary of runtimes per language
 LANG_RUNTIME_MATRIX = {
+    'cxx': ['cxx'],             # This is actually debian8.
     'go': ['go1.7', 'go1.8'],
     'java': ['java_oracle8'],
 }
 
 # Dictionary of releases per language.  For each language, we need to provide
-# a tuple of release tag (used as the tag for the GCR image) and also github hash.
+# a release tag pointing to the latest build of the branch.
 LANG_RELEASE_MATRIX = {
-    'go': ['v1.0.1-GA', 'v1.3.0'],
-    'java': ['v1.0.3', 'v1.1.2'],
+    'cxx': [
+        'v1.0.1',
+        'v1.1.4',
+        'v1.2.5',
+        'v1.3.9',
+        'v1.4.2',
+    ],
+    'go': [
+        'v1.0.5',
+        'v1.2.1',
+        'v1.3.0',
+        'v1.4.2',
+    ],
+    'java': [
+        'v1.0.3',
+        'v1.1.2',
+        'v1.2.0',
+        'v1.3.1',
+        'v1.4.0',
+        'v1.5.0',
+    ],
 }
diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py
index b1b95ed..4315c82 100755
--- a/tools/interop_matrix/run_interop_matrix_tests.py
+++ b/tools/interop_matrix/run_interop_matrix_tests.py
@@ -125,7 +125,6 @@
       # Only line start with 'docker run' are test cases.
       for line in f.readlines():
         if line.startswith('docker run'):
-          line = line.replace('docker run', 'gcloud docker -- run')
           m = re.search('--test_case=(.*)"', line)
           shortname = m.group(1) if m else 'unknown_test'
           spec = jobset.JobSpec(cmdline=line,
@@ -152,6 +151,8 @@
   for image_tuple in images:
     release, image = image_tuple
     jobset.message('START', 'Testing %s' % image, do_newline=True)
+    # Download the docker image before running each test case.
+    subprocess.check_call(['gcloud', 'docker', '--', 'pull', image])
     _docker_images_cleanup.append(image)
     job_spec_list = find_test_cases(lang,release)
     num_failures, resultset = jobset.run(job_spec_list,
@@ -167,7 +168,7 @@
         _xml_report_tree,
         resultset,
         'grpc_interop_matrix',
-        '%s__%s:%s'%(lang,runtime,release),
+        '%s__%s %s'%(lang,runtime,release),
         str(uuid.uuid4()))
 
 _docker_images_cleanup = []
diff --git a/tools/interop_matrix/testcases/cxx__master b/tools/interop_matrix/testcases/cxx__master
new file mode 100755
index 0000000..ccd2859
--- /dev/null
+++ b/tools/interop_matrix/testcases/cxx__master
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo "Testing ${docker_image:=grpc_interop_cxx:1423f288-ac00-4f3a-9885-771258eecae3}"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --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 -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
diff --git a/tools/jenkins/run_bazel_full.sh b/tools/jenkins/run_bazel_full.sh
index edde1bc..3436a8f 100755
--- a/tools/jenkins/run_bazel_full.sh
+++ b/tools/jenkins/run_bazel_full.sh
@@ -20,6 +20,4 @@
 
 export DOCKERFILE_DIR=tools/dockerfile/test/bazel
 export DOCKER_RUN_SCRIPT=tools/jenkins/run_bazel_full_in_docker.sh
-# Warn PR author if they make a change to the bazel directory
-tools/run_tests/python_utils/check_bazel_dir.py
 exec tools/run_tests/dockerize/build_and_run_docker.sh
diff --git a/tools/mkowners/mkowners.py b/tools/mkowners/mkowners.py
new file mode 100755
index 0000000..e0ad998
--- /dev/null
+++ b/tools/mkowners/mkowners.py
@@ -0,0 +1,228 @@
+#!/usr/bin/env python3
+# 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.
+
+import argparse
+import collections
+import operator
+import os
+import re
+import subprocess
+
+#
+# Find the root of the git tree
+#
+
+git_root = (subprocess
+            .check_output(['git', 'rev-parse', '--show-toplevel'])
+            .decode('utf-8')
+            .strip())
+
+#
+# Parse command line arguments
+#
+
+default_out = os.path.join(git_root, '.github', 'CODEOWNERS')
+
+argp = argparse.ArgumentParser('Generate .github/CODEOWNERS file')
+argp.add_argument('--out', '-o',
+                  type=str,
+                  default=default_out,
+                  help='Output file (default %s)' % default_out)
+args = argp.parse_args()
+
+#
+# Walk git tree to locate all OWNERS files
+#
+
+owners_files = [os.path.join(root, 'OWNERS')
+                for root, dirs, files in os.walk(git_root)
+                if 'OWNERS' in files]
+
+#
+# Parse owners files
+#
+
+Owners = collections.namedtuple('Owners', 'parent directives dir')
+Directive = collections.namedtuple('Directive', 'who globs')
+
+def parse_owners(filename):
+  with open(filename) as f:
+    src = f.read().splitlines()
+  parent = True
+  directives = []
+  for line in src:
+    line = line.strip()
+    # line := directive | comment
+    if not line: continue
+    if line[0] == '#': continue
+    # it's a directive
+    directive = None
+    if line == 'set noparent':
+      parent = False
+    elif line == '*':
+      directive = Directive(who='*', globs=[])
+    elif ' ' in line:
+      (who, globs) = line.split(' ', 1)
+      globs_list = [glob
+                    for glob in globs.split(' ')
+                    if glob]
+      directive = Directive(who=who, globs=globs_list)
+    else:
+      directive = Directive(who=line, globs=[])
+    if directive:
+      directives.append(directive)
+  return Owners(parent=parent,
+                directives=directives,
+                dir=os.path.relpath(os.path.dirname(filename), git_root))
+
+owners_data = sorted([parse_owners(filename)
+                      for filename in owners_files],
+                     key=operator.attrgetter('dir'))
+
+#
+# Modify owners so that parented OWNERS files point to the actual
+# Owners tuple with their parent field
+#
+
+new_owners_data = []
+for owners in owners_data:
+  if owners.parent == True:
+    best_parent = None
+    best_parent_score = None
+    for possible_parent in owners_data:
+      if possible_parent is owners: continue
+      rel = os.path.relpath(owners.dir, possible_parent.dir)
+      # '..' ==> we had to walk up from possible_parent to get to owners
+      #      ==> not a parent
+      if '..' in rel: continue
+      depth = len(rel.split(os.sep))
+      if not best_parent or depth < best_parent_score:
+        best_parent = possible_parent
+        best_parent_score = depth
+    if best_parent:
+      owners = owners._replace(parent = best_parent.dir)
+    else:
+      owners = owners._replace(parent = None)
+  new_owners_data.append(owners)
+owners_data = new_owners_data
+
+#
+# In bottom to top order, process owners data structures to build up
+# a CODEOWNERS file for GitHub
+#
+
+def full_dir(rules_dir, sub_path):
+  return os.path.join(rules_dir, sub_path) if rules_dir != '.' else sub_path
+
+# glob using git
+gg_cache = {}
+def git_glob(glob):
+  global gg_cache
+  if glob in gg_cache: return gg_cache[glob]
+  r = set(subprocess
+      .check_output(['git', 'ls-files', os.path.join(git_root, glob)])
+      .decode('utf-8')
+      .strip()
+      .splitlines())
+  gg_cache[glob] = r
+  return r
+
+def expand_directives(root, directives):
+  globs = collections.OrderedDict()
+  # build a table of glob --> owners
+  for directive in directives:
+    for glob in directive.globs or ['**']:
+      if glob not in globs:
+        globs[glob] = []
+      if directive.who not in globs[glob]:
+        globs[glob].append(directive.who)
+  # expand owners for intersecting globs
+  sorted_globs = sorted(globs.keys(),
+                        key=lambda g: len(git_glob(full_dir(root, g))),
+                        reverse=True)
+  out_globs = collections.OrderedDict()
+  for glob_add in sorted_globs:
+    who_add = globs[glob_add]
+    pre_items = [i for i in out_globs.items()]
+    out_globs[glob_add] = who_add.copy()
+    for glob_have, who_have in pre_items:
+      files_add = git_glob(full_dir(root, glob_add))
+      files_have = git_glob(full_dir(root, glob_have))
+      intersect = files_have.intersection(files_add)
+      if intersect:
+        for f in sorted(files_add): # sorted to ensure merge stability
+          if f not in intersect:
+            out_globs[os.path.relpath(f, start=root)] = who_add
+        for who in who_have:
+          if who not in out_globs[glob_add]:
+            out_globs[glob_add].append(who)
+  return out_globs
+
+def add_parent_to_globs(parent, globs, globs_dir):
+  if not parent: return
+  for owners in owners_data:
+    if owners.dir == parent:
+      owners_globs = expand_directives(owners.dir, owners.directives)
+      for oglob, oglob_who in owners_globs.items():
+        for gglob, gglob_who in globs.items():
+          files_parent = git_glob(full_dir(owners.dir, oglob))
+          files_child = git_glob(full_dir(globs_dir, gglob))
+          intersect = files_parent.intersection(files_child)
+          gglob_who_orig = gglob_who.copy()
+          if intersect:
+            for f in sorted(files_child): # sorted to ensure merge stability
+              if f not in intersect:
+                who = gglob_who_orig.copy()
+                globs[os.path.relpath(f, start=globs_dir)] = who
+            for who in oglob_who:
+              if who not in gglob_who:
+                gglob_who.append(who)
+      add_parent_to_globs(owners.parent, globs, globs_dir)
+      return
+  assert(False)
+
+todo = owners_data.copy()
+done = set()
+with open(args.out, 'w') as out:
+  out.write('# Auto-generated by the tools/mkowners/mkowners.py tool\n')
+  out.write('# Uses OWNERS files in different modules throughout the\n')
+  out.write('# repository as the source of truth for module ownership.\n')
+  written_globs = []
+  while todo:
+    head, *todo = todo
+    if head.parent and not head.parent in done:
+      todo.append(head)
+      continue
+    globs = expand_directives(head.dir, head.directives)
+    add_parent_to_globs(head.parent, globs, head.dir)
+    for glob, owners in globs.items():
+      skip = False
+      for glob1, owners1, dir1 in reversed(written_globs):
+        files = git_glob(full_dir(head.dir, glob))
+        files1 = git_glob(full_dir(dir1, glob1))
+        intersect = files.intersection(files1)
+        if files == intersect:
+          if sorted(owners) == sorted(owners1):
+            skip = True # nothing new in this rule
+            break
+        elif intersect:
+          # continuing would cause a semantic change since some files are
+          # affected differently by this rule and CODEOWNERS is order dependent
+          break
+      if not skip:
+        out.write('/%s %s\n' % (
+            full_dir(head.dir, glob), ' '.join(owners)))
+        written_globs.append((glob, owners, head.dir))
+    done.add(head.dir)
diff --git a/tools/profiling/microbenchmarks/bm_diff/bm_diff.py b/tools/profiling/microbenchmarks/bm_diff/bm_diff.py
index 809817a..a41d0f0 100755
--- a/tools/profiling/microbenchmarks/bm_diff/bm_diff.py
+++ b/tools/profiling/microbenchmarks/bm_diff/bm_diff.py
@@ -67,6 +67,12 @@
     default=20,
     help='Number of times to loops the benchmarks. Must match what was passed to bm_run.py'
   )
+  argp.add_argument(
+    '-r',
+    '--regex',
+    type=str,
+    default="",
+    help='Regex to filter benchmarks run')
   argp.add_argument('--counters', dest='counters', action='store_true')
   argp.add_argument('--no-counters', dest='counters', action='store_false')
   argp.set_defaults(counters=True)
@@ -144,7 +150,7 @@
 def fmt_dict(d):
   return ''.join(["    " + k + ": " + str(d[k]) + "\n" for k in d])
 
-def diff(bms, loops, track, old, new, counters):
+def diff(bms, loops, regex, track, old, new, counters):
   benchmarks = collections.defaultdict(Benchmark)
 
   badjson_files = {}
@@ -153,7 +159,8 @@
     for loop in range(0, loops):
       for line in subprocess.check_output(
         ['bm_diff_%s/opt/%s' % (old, bm),
-         '--benchmark_list_tests']).splitlines():
+         '--benchmark_list_tests', 
+         '--benchmark_filter=%s' % regex]).splitlines():
         stripped_line = line.strip().replace("/", "_").replace(
           "<", "_").replace(">", "_").replace(", ", "_")
         js_new_opt = _read_json('%s.%s.opt.%s.%d.json' %
@@ -211,6 +218,6 @@
 
 if __name__ == '__main__':
   args = _args()
-  diff, note = diff(args.benchmarks, args.loops, args.track, args.old,
+  diff, note = diff(args.benchmarks, args.loops, args.regex, args.track, args.old,
             args.new, args.counters)
   print('%s\n%s' % (note, diff if diff else "No performance differences"))
diff --git a/tools/profiling/microbenchmarks/bm_diff/bm_main.py b/tools/profiling/microbenchmarks/bm_diff/bm_main.py
index 8b4e0cb..5aa11ac 100755
--- a/tools/profiling/microbenchmarks/bm_diff/bm_main.py
+++ b/tools/profiling/microbenchmarks/bm_diff/bm_main.py
@@ -63,10 +63,10 @@
     help='Name of baseline run to compare to. Ususally just called "old"')
   argp.add_argument(
     '-r',
-    '--repetitions',
-    type=int,
-    default=1,
-    help='Number of repetitions to pass to the benchmarks')
+    '--regex',
+    type=str,
+    default="",
+    help='Regex to filter benchmarks run')
   argp.add_argument(
     '-l',
     '--loops',
@@ -125,10 +125,10 @@
       subprocess.check_call(['git', 'checkout', where_am_i])
       subprocess.check_call(['git', 'submodule', 'update'])
 
-  bm_run.run('new', args.benchmarks, args.jobs, args.loops, args.repetitions, args.counters)
-  bm_run.run(old, args.benchmarks, args.jobs, args.loops, args.repetitions, args.counters)
+  bm_run.run('new', args.benchmarks, args.jobs, args.loops, args.regex, args.counters)
+  bm_run.run(old, args.benchmarks, args.jobs, args.loops, args.regex, args.counters)
 
-  diff, note = bm_diff.diff(args.benchmarks, args.loops, args.track, old,
+  diff, note = bm_diff.diff(args.benchmarks, args.loops, args.regex, args.track, old,
                 'new', args.counters)
   if diff:
     text = '[%s] Performance differences noted:\n%s' % (args.pr_comment_name, diff)
diff --git a/tools/profiling/microbenchmarks/bm_diff/bm_run.py b/tools/profiling/microbenchmarks/bm_diff/bm_run.py
index 72b3d3c..206f7c5 100755
--- a/tools/profiling/microbenchmarks/bm_diff/bm_run.py
+++ b/tools/profiling/microbenchmarks/bm_diff/bm_run.py
@@ -56,10 +56,10 @@
   )
   argp.add_argument(
     '-r',
-    '--repetitions',
-    type=int,
-    default=1,
-    help='Number of repetitions to pass to the benchmarks')
+    '--regex',
+    type=str,
+    default="",
+    help='Regex to filter benchmarks run')
   argp.add_argument(
     '-l',
     '--loops',
@@ -77,18 +77,17 @@
   return args
 
 
-def _collect_bm_data(bm, cfg, name, reps, idx, loops):
+def _collect_bm_data(bm, cfg, name, regex, idx, loops):
   jobs_list = []
   for line in subprocess.check_output(
     ['bm_diff_%s/%s/%s' % (name, cfg, bm),
-     '--benchmark_list_tests']).splitlines():
+     '--benchmark_list_tests', '--benchmark_filter=%s' % regex]).splitlines():
     stripped_line = line.strip().replace("/", "_").replace(
       "<", "_").replace(">", "_").replace(", ", "_")
     cmd = [
       'bm_diff_%s/%s/%s' % (name, cfg, bm), '--benchmark_filter=^%s$' %
       line, '--benchmark_out=%s.%s.%s.%s.%d.json' %
       (bm, stripped_line, cfg, name, idx), '--benchmark_out_format=json',
-      '--benchmark_repetitions=%d' % (reps)
     ]
     jobs_list.append(
       jobset.JobSpec(
@@ -100,13 +99,13 @@
   return jobs_list
 
 
-def run(name, benchmarks, jobs, loops, reps, counters):
+def run(name, benchmarks, jobs, loops, regex, counters):
   jobs_list = []
   for loop in range(0, loops):
     for bm in benchmarks:
-      jobs_list += _collect_bm_data(bm, 'opt', name, reps, loop, loops)
+      jobs_list += _collect_bm_data(bm, 'opt', name, regex, loop, loops)
       if counters:
-        jobs_list += _collect_bm_data(bm, 'counters', name, reps, loop,
+        jobs_list += _collect_bm_data(bm, 'counters', name, regex, loop,
                         loops)
   random.shuffle(jobs_list, random.SystemRandom().random)
   jobset.run(jobs_list, maxjobs=jobs)
@@ -114,4 +113,4 @@
 
 if __name__ == '__main__':
   args = _args()
-  run(args.name, args.benchmarks, args.jobs, args.loops, args.repetitions, args.counters)
+  run(args.name, args.benchmarks, args.jobs, args.loops, args.regex, args.counters)
diff --git a/tools/run_tests/artifacts/build_artifact_python.bat b/tools/run_tests/artifacts/build_artifact_python.bat
index 4c34fc5..3a05641 100644
--- a/tools/run_tests/artifacts/build_artifact_python.bat
+++ b/tools/run_tests/artifacts/build_artifact_python.bat
@@ -12,8 +12,8 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-
-set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;%PATH%
+@rem set path to python & mingw compiler
+set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;C:\tools\msys64\mingw%2\bin;%PATH%
 
 pip install --upgrade six
 pip install --upgrade setuptools
diff --git a/tools/run_tests/dockerize/build_interop_image.sh b/tools/run_tests/dockerize/build_interop_image.sh
index fa63185..9d8ad53 100755
--- a/tools/run_tests/dockerize/build_interop_image.sh
+++ b/tools/run_tests/dockerize/build_interop_image.sh
@@ -62,13 +62,19 @@
 # on OSX use md5 instead of sha1sum
 if which sha1sum > /dev/null;
 then
-  BASE_IMAGE=${BASE_NAME}_base:`sha1sum tools/dockerfile/interoptest/$BASE_NAME/Dockerfile | cut -f1 -d\ `
+  BASE_IMAGE=${BASE_NAME}_`sha1sum tools/dockerfile/interoptest/$BASE_NAME/Dockerfile | cut -f1 -d\ `
 else
-  BASE_IMAGE=${BASE_NAME}_base:`md5 -r tools/dockerfile/interoptest/$BASE_NAME/Dockerfile | cut -f1 -d\ `
+  BASE_IMAGE=${BASE_NAME}_`md5 -r tools/dockerfile/interoptest/$BASE_NAME/Dockerfile | cut -f1 -d\ `
 fi
 
-# Make sure base docker image has been built. Should be instantaneous if so.
-docker build -t $BASE_IMAGE --force-rm=true tools/dockerfile/interoptest/$BASE_NAME || exit $?
+if [ "$DOCKERHUB_ORGANIZATION" != "" ]
+then
+  BASE_IMAGE=$DOCKERHUB_ORGANIZATION/$BASE_IMAGE
+  docker pull $BASE_IMAGE
+else
+  # Make sure docker image has been built. Should be instantaneous if so.
+  docker build -t $BASE_IMAGE --force-rm=true tools/dockerfile/interoptest/$BASE_NAME || exit $?
+fi
 
 # Create a local branch so the child Docker script won't complain
 git branch -f jenkins-docker
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 477a258..d5eba6e 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -174,6 +174,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "byte_stream_test", 
+    "src": [
+      "test/core/transport/byte_stream_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "census_context_test", 
     "src": [
       "test/core/census/context_test.c"
@@ -2173,6 +2190,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "stream_compression_test", 
+    "src": [
+      "test/core/compression/stream_compression_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "stream_owned_slice_test", 
     "src": [
       "test/core/transport/stream_owned_slice_test.c"
@@ -2473,10 +2507,10 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util"
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2531,11 +2565,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2552,11 +2586,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2573,11 +2607,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2594,11 +2628,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2615,11 +2649,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2636,11 +2670,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2657,11 +2691,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2678,11 +2712,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2699,11 +2733,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2720,11 +2754,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2741,11 +2775,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2762,11 +2796,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2783,11 +2817,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -2804,11 +2838,11 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
       "grpc_benchmark", 
-      "grpc_test_util"
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -3646,6 +3680,7 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
       "qps"
@@ -3815,6 +3850,7 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
       "qps"
@@ -3852,10 +3888,10 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util"
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [
       "src/proto/grpc/testing/echo.grpc.pb.h", 
@@ -3935,6 +3971,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_request_call_test", 
+    "src": [
+      "test/cpp/server/server_request_call_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
       "grpc", 
       "grpc++", 
       "grpc++_test_util", 
@@ -4036,9 +4098,9 @@
   {
     "deps": [
       "gpr", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_config"
+      "grpc++_test_config", 
+      "grpc++_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -4054,10 +4116,10 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util"
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [], 
     "is_filegroup": false, 
@@ -5194,6 +5256,24 @@
   }, 
   {
     "deps": [
+      "end2end_tests", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "src": [
+      "test/core/end2end/fixtures/inproc.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "end2end_nosec_tests", 
       "gpr", 
       "gpr_test_util", 
@@ -5446,6 +5526,24 @@
   }, 
   {
     "deps": [
+      "end2end_nosec_tests", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "src": [
+      "test/core/end2end/fixtures/inproc.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "gpr", 
       "gpr_test_util", 
       "grpc", 
@@ -5729,6 +5827,7 @@
       "grpc_transport_chttp2_client_secure", 
       "grpc_transport_chttp2_server_insecure", 
       "grpc_transport_chttp2_server_secure", 
+      "grpc_transport_inproc", 
       "grpc_workaround_cronet_compression_filter"
     ], 
     "headers": [], 
@@ -5777,7 +5876,6 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
-      "grpc_base", 
       "grpc_test_util_base"
     ], 
     "headers": [
@@ -5803,7 +5901,6 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
-      "grpc", 
       "grpc_test_util_base", 
       "grpc_unsecure"
     ], 
@@ -5834,6 +5931,7 @@
       "grpc_server_backward_compatibility", 
       "grpc_transport_chttp2_client_insecure", 
       "grpc_transport_chttp2_server_insecure", 
+      "grpc_transport_inproc", 
       "grpc_workaround_cronet_compression_filter"
     ], 
     "headers": [], 
@@ -5890,6 +5988,7 @@
   }, 
   {
     "deps": [
+      "gpr", 
       "grpc", 
       "grpc++_base", 
       "grpc++_codegen_base", 
@@ -6076,9 +6175,52 @@
   }, 
   {
     "deps": [
+      "grpc++_codegen_base", 
+      "grpc++_codegen_base_src", 
+      "grpc++_codegen_proto", 
+      "grpc++_config_proto", 
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [
+      "src/proto/grpc/health/v1/health.grpc.pb.h", 
+      "src/proto/grpc/health/v1/health.pb.h", 
+      "src/proto/grpc/health/v1/health_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h", 
+      "src/proto/grpc/testing/duplicate/echo_duplicate.pb.h", 
+      "src/proto/grpc/testing/duplicate/echo_duplicate_mock.grpc.pb.h", 
+      "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", 
+      "test/cpp/end2end/test_service_impl.h", 
+      "test/cpp/util/byte_buffer_proto_helper.h", 
+      "test/cpp/util/string_ref_helper.h", 
+      "test/cpp/util/subprocess.h"
+    ], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "grpc++_test_util_unsecure", 
+    "src": [
+      "test/cpp/end2end/test_service_impl.cc", 
+      "test/cpp/end2end/test_service_impl.h", 
+      "test/cpp/util/byte_buffer_proto_helper.cc", 
+      "test/cpp/util/byte_buffer_proto_helper.h", 
+      "test/cpp/util/string_ref_helper.cc", 
+      "test/cpp/util/string_ref_helper.h", 
+      "test/cpp/util/subprocess.cc", 
+      "test/cpp/util/subprocess.h"
+    ], 
+    "third_party": false, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
       "gpr", 
-      "grpc", 
-      "grpc++_base", 
+      "grpc++_base_unsecure", 
       "grpc++_codegen_base", 
       "grpc++_codegen_base_src", 
       "grpc_unsecure"
@@ -6098,9 +6240,9 @@
   {
     "deps": [
       "benchmark", 
-      "grpc", 
-      "grpc++", 
-      "grpc_test_util"
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
     ], 
     "headers": [
       "test/cpp/microbenchmarks/fullstack_context_mutators.h", 
@@ -7256,6 +7398,7 @@
       "test/core/end2end/tests/payload.c", 
       "test/core/end2end/tests/ping.c", 
       "test/core/end2end/tests/ping_pong_streaming.c", 
+      "test/core/end2end/tests/proxy_auth.c", 
       "test/core/end2end/tests/registered_call.c", 
       "test/core/end2end/tests/request_with_flags.c", 
       "test/core/end2end/tests/request_with_payload.c", 
@@ -7333,6 +7476,7 @@
       "test/core/end2end/tests/payload.c", 
       "test/core/end2end/tests/ping.c", 
       "test/core/end2end/tests/ping_pong_streaming.c", 
+      "test/core/end2end/tests/proxy_auth.c", 
       "test/core/end2end/tests/registered_call.c", 
       "test/core/end2end/tests/request_with_flags.c", 
       "test/core/end2end/tests/request_with_payload.c", 
@@ -7424,6 +7568,65 @@
   }, 
   {
     "deps": [
+      "gpr_base_headers"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "gpr_base", 
+    "src": [
+      "src/core/lib/profiling/basic_timers.c", 
+      "src/core/lib/profiling/stap_timers.c", 
+      "src/core/lib/support/alloc.c", 
+      "src/core/lib/support/arena.c", 
+      "src/core/lib/support/atm.c", 
+      "src/core/lib/support/avl.c", 
+      "src/core/lib/support/backoff.c", 
+      "src/core/lib/support/cmdline.c", 
+      "src/core/lib/support/cpu_iphone.c", 
+      "src/core/lib/support/cpu_linux.c", 
+      "src/core/lib/support/cpu_posix.c", 
+      "src/core/lib/support/cpu_windows.c", 
+      "src/core/lib/support/env_linux.c", 
+      "src/core/lib/support/env_posix.c", 
+      "src/core/lib/support/env_windows.c", 
+      "src/core/lib/support/histogram.c", 
+      "src/core/lib/support/host_port.c", 
+      "src/core/lib/support/log.c", 
+      "src/core/lib/support/log_android.c", 
+      "src/core/lib/support/log_linux.c", 
+      "src/core/lib/support/log_posix.c", 
+      "src/core/lib/support/log_windows.c", 
+      "src/core/lib/support/mpscq.c", 
+      "src/core/lib/support/murmur_hash.c", 
+      "src/core/lib/support/stack_lockfree.c", 
+      "src/core/lib/support/string.c", 
+      "src/core/lib/support/string_posix.c", 
+      "src/core/lib/support/string_util_windows.c", 
+      "src/core/lib/support/string_windows.c", 
+      "src/core/lib/support/subprocess_posix.c", 
+      "src/core/lib/support/subprocess_windows.c", 
+      "src/core/lib/support/sync.c", 
+      "src/core/lib/support/sync_posix.c", 
+      "src/core/lib/support/sync_windows.c", 
+      "src/core/lib/support/thd.c", 
+      "src/core/lib/support/thd_posix.c", 
+      "src/core/lib/support/thd_windows.c", 
+      "src/core/lib/support/time.c", 
+      "src/core/lib/support/time_posix.c", 
+      "src/core/lib/support/time_precise.c", 
+      "src/core/lib/support/time_windows.c", 
+      "src/core/lib/support/tls_pthread.c", 
+      "src/core/lib/support/tmpfile_msys.c", 
+      "src/core/lib/support/tmpfile_posix.c", 
+      "src/core/lib/support/tmpfile_windows.c", 
+      "src/core/lib/support/wrap_memcpy.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
       "gpr_codegen"
     ], 
     "headers": [
@@ -7474,7 +7677,7 @@
     ], 
     "is_filegroup": true, 
     "language": "c", 
-    "name": "gpr_base", 
+    "name": "gpr_base_headers", 
     "src": [
       "include/grpc/support/alloc.h", 
       "include/grpc/support/atm.h", 
@@ -7502,70 +7705,24 @@
       "include/grpc/support/tls_msvc.h", 
       "include/grpc/support/tls_pthread.h", 
       "include/grpc/support/useful.h", 
-      "src/core/lib/profiling/basic_timers.c", 
-      "src/core/lib/profiling/stap_timers.c", 
       "src/core/lib/profiling/timers.h", 
-      "src/core/lib/support/alloc.c", 
-      "src/core/lib/support/arena.c", 
       "src/core/lib/support/arena.h", 
-      "src/core/lib/support/atm.c", 
       "src/core/lib/support/atomic.h", 
       "src/core/lib/support/atomic_with_atm.h", 
       "src/core/lib/support/atomic_with_std.h", 
-      "src/core/lib/support/avl.c", 
-      "src/core/lib/support/backoff.c", 
       "src/core/lib/support/backoff.h", 
       "src/core/lib/support/block_annotate.h", 
-      "src/core/lib/support/cmdline.c", 
-      "src/core/lib/support/cpu_iphone.c", 
-      "src/core/lib/support/cpu_linux.c", 
-      "src/core/lib/support/cpu_posix.c", 
-      "src/core/lib/support/cpu_windows.c", 
       "src/core/lib/support/env.h", 
-      "src/core/lib/support/env_linux.c", 
-      "src/core/lib/support/env_posix.c", 
-      "src/core/lib/support/env_windows.c", 
-      "src/core/lib/support/histogram.c", 
-      "src/core/lib/support/host_port.c", 
-      "src/core/lib/support/log.c", 
-      "src/core/lib/support/log_android.c", 
-      "src/core/lib/support/log_linux.c", 
-      "src/core/lib/support/log_posix.c", 
-      "src/core/lib/support/log_windows.c", 
       "src/core/lib/support/memory.h", 
-      "src/core/lib/support/mpscq.c", 
       "src/core/lib/support/mpscq.h", 
-      "src/core/lib/support/murmur_hash.c", 
       "src/core/lib/support/murmur_hash.h", 
       "src/core/lib/support/spinlock.h", 
-      "src/core/lib/support/stack_lockfree.c", 
       "src/core/lib/support/stack_lockfree.h", 
-      "src/core/lib/support/string.c", 
       "src/core/lib/support/string.h", 
-      "src/core/lib/support/string_posix.c", 
-      "src/core/lib/support/string_util_windows.c", 
-      "src/core/lib/support/string_windows.c", 
       "src/core/lib/support/string_windows.h", 
-      "src/core/lib/support/subprocess_posix.c", 
-      "src/core/lib/support/subprocess_windows.c", 
-      "src/core/lib/support/sync.c", 
-      "src/core/lib/support/sync_posix.c", 
-      "src/core/lib/support/sync_windows.c", 
-      "src/core/lib/support/thd.c", 
       "src/core/lib/support/thd_internal.h", 
-      "src/core/lib/support/thd_posix.c", 
-      "src/core/lib/support/thd_windows.c", 
-      "src/core/lib/support/time.c", 
-      "src/core/lib/support/time_posix.c", 
-      "src/core/lib/support/time_precise.c", 
       "src/core/lib/support/time_precise.h", 
-      "src/core/lib/support/time_windows.c", 
-      "src/core/lib/support/tls_pthread.c", 
-      "src/core/lib/support/tmpfile.h", 
-      "src/core/lib/support/tmpfile_msys.c", 
-      "src/core/lib/support/tmpfile_posix.c", 
-      "src/core/lib/support/tmpfile_windows.c", 
-      "src/core/lib/support/wrap_memcpy.c"
+      "src/core/lib/support/tmpfile.h"
     ], 
     "third_party": false, 
     "type": "filegroup"
@@ -7607,9 +7764,180 @@
   {
     "deps": [
       "gpr", 
+      "grpc", 
+      "grpc++_codegen_base", 
+      "grpc++_common"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc++_base", 
+    "src": [], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc++_codegen_base", 
+      "grpc++_common", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc++_base_unsecure", 
+    "src": [], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base_headers", 
       "grpc_codegen", 
       "grpc_trace"
     ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_base", 
+    "src": [
+      "src/core/lib/channel/channel_args.c", 
+      "src/core/lib/channel/channel_stack.c", 
+      "src/core/lib/channel/channel_stack_builder.c", 
+      "src/core/lib/channel/connected_channel.c", 
+      "src/core/lib/channel/handshaker.c", 
+      "src/core/lib/channel/handshaker_factory.c", 
+      "src/core/lib/channel/handshaker_registry.c", 
+      "src/core/lib/compression/compression.c", 
+      "src/core/lib/compression/message_compress.c", 
+      "src/core/lib/compression/stream_compression.c", 
+      "src/core/lib/http/format_request.c", 
+      "src/core/lib/http/httpcli.c", 
+      "src/core/lib/http/parser.c", 
+      "src/core/lib/iomgr/closure.c", 
+      "src/core/lib/iomgr/combiner.c", 
+      "src/core/lib/iomgr/endpoint.c", 
+      "src/core/lib/iomgr/endpoint_pair_posix.c", 
+      "src/core/lib/iomgr/endpoint_pair_uv.c", 
+      "src/core/lib/iomgr/endpoint_pair_windows.c", 
+      "src/core/lib/iomgr/error.c", 
+      "src/core/lib/iomgr/ev_epoll1_linux.c", 
+      "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c", 
+      "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c", 
+      "src/core/lib/iomgr/ev_epollex_linux.c", 
+      "src/core/lib/iomgr/ev_epollsig_linux.c", 
+      "src/core/lib/iomgr/ev_poll_posix.c", 
+      "src/core/lib/iomgr/ev_posix.c", 
+      "src/core/lib/iomgr/ev_windows.c", 
+      "src/core/lib/iomgr/exec_ctx.c", 
+      "src/core/lib/iomgr/executor.c", 
+      "src/core/lib/iomgr/iocp_windows.c", 
+      "src/core/lib/iomgr/iomgr.c", 
+      "src/core/lib/iomgr/iomgr_posix.c", 
+      "src/core/lib/iomgr/iomgr_uv.c", 
+      "src/core/lib/iomgr/iomgr_windows.c", 
+      "src/core/lib/iomgr/is_epollexclusive_available.c", 
+      "src/core/lib/iomgr/load_file.c", 
+      "src/core/lib/iomgr/lockfree_event.c", 
+      "src/core/lib/iomgr/network_status_tracker.c", 
+      "src/core/lib/iomgr/polling_entity.c", 
+      "src/core/lib/iomgr/pollset_set_uv.c", 
+      "src/core/lib/iomgr/pollset_set_windows.c", 
+      "src/core/lib/iomgr/pollset_uv.c", 
+      "src/core/lib/iomgr/pollset_windows.c", 
+      "src/core/lib/iomgr/resolve_address_posix.c", 
+      "src/core/lib/iomgr/resolve_address_uv.c", 
+      "src/core/lib/iomgr/resolve_address_windows.c", 
+      "src/core/lib/iomgr/resource_quota.c", 
+      "src/core/lib/iomgr/sockaddr_utils.c", 
+      "src/core/lib/iomgr/socket_factory_posix.c", 
+      "src/core/lib/iomgr/socket_mutator.c", 
+      "src/core/lib/iomgr/socket_utils_common_posix.c", 
+      "src/core/lib/iomgr/socket_utils_linux.c", 
+      "src/core/lib/iomgr/socket_utils_posix.c", 
+      "src/core/lib/iomgr/socket_utils_uv.c", 
+      "src/core/lib/iomgr/socket_utils_windows.c", 
+      "src/core/lib/iomgr/socket_windows.c", 
+      "src/core/lib/iomgr/tcp_client_posix.c", 
+      "src/core/lib/iomgr/tcp_client_uv.c", 
+      "src/core/lib/iomgr/tcp_client_windows.c", 
+      "src/core/lib/iomgr/tcp_posix.c", 
+      "src/core/lib/iomgr/tcp_server_posix.c", 
+      "src/core/lib/iomgr/tcp_server_utils_posix_common.c", 
+      "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", 
+      "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", 
+      "src/core/lib/iomgr/tcp_server_uv.c", 
+      "src/core/lib/iomgr/tcp_server_windows.c", 
+      "src/core/lib/iomgr/tcp_uv.c", 
+      "src/core/lib/iomgr/tcp_windows.c", 
+      "src/core/lib/iomgr/time_averaged_stats.c", 
+      "src/core/lib/iomgr/timer_generic.c", 
+      "src/core/lib/iomgr/timer_heap.c", 
+      "src/core/lib/iomgr/timer_manager.c", 
+      "src/core/lib/iomgr/timer_uv.c", 
+      "src/core/lib/iomgr/udp_server.c", 
+      "src/core/lib/iomgr/unix_sockets_posix.c", 
+      "src/core/lib/iomgr/unix_sockets_posix_noop.c", 
+      "src/core/lib/iomgr/wakeup_fd_cv.c", 
+      "src/core/lib/iomgr/wakeup_fd_eventfd.c", 
+      "src/core/lib/iomgr/wakeup_fd_nospecial.c", 
+      "src/core/lib/iomgr/wakeup_fd_pipe.c", 
+      "src/core/lib/iomgr/wakeup_fd_posix.c", 
+      "src/core/lib/json/json.c", 
+      "src/core/lib/json/json_reader.c", 
+      "src/core/lib/json/json_string.c", 
+      "src/core/lib/json/json_writer.c", 
+      "src/core/lib/slice/b64.c", 
+      "src/core/lib/slice/percent_encoding.c", 
+      "src/core/lib/slice/slice.c", 
+      "src/core/lib/slice/slice_buffer.c", 
+      "src/core/lib/slice/slice_hash_table.c", 
+      "src/core/lib/slice/slice_intern.c", 
+      "src/core/lib/slice/slice_string_helpers.c", 
+      "src/core/lib/surface/alarm.c", 
+      "src/core/lib/surface/api_trace.c", 
+      "src/core/lib/surface/byte_buffer.c", 
+      "src/core/lib/surface/byte_buffer_reader.c", 
+      "src/core/lib/surface/call.c", 
+      "src/core/lib/surface/call_details.c", 
+      "src/core/lib/surface/call_log_batch.c", 
+      "src/core/lib/surface/channel.c", 
+      "src/core/lib/surface/channel_init.c", 
+      "src/core/lib/surface/channel_ping.c", 
+      "src/core/lib/surface/channel_stack_type.c", 
+      "src/core/lib/surface/completion_queue.c", 
+      "src/core/lib/surface/completion_queue_factory.c", 
+      "src/core/lib/surface/event_string.c", 
+      "src/core/lib/surface/lame_client.cc", 
+      "src/core/lib/surface/metadata_array.c", 
+      "src/core/lib/surface/server.c", 
+      "src/core/lib/surface/validate_metadata.c", 
+      "src/core/lib/surface/version.c", 
+      "src/core/lib/transport/bdp_estimator.c", 
+      "src/core/lib/transport/byte_stream.c", 
+      "src/core/lib/transport/connectivity_state.c", 
+      "src/core/lib/transport/error_utils.c", 
+      "src/core/lib/transport/metadata.c", 
+      "src/core/lib/transport/metadata_batch.c", 
+      "src/core/lib/transport/pid_controller.c", 
+      "src/core/lib/transport/service_config.c", 
+      "src/core/lib/transport/static_metadata.c", 
+      "src/core/lib/transport/status_conversion.c", 
+      "src/core/lib/transport/timeout_encoding.c", 
+      "src/core/lib/transport/transport.c", 
+      "src/core/lib/transport/transport_op_string.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_codegen", 
+      "grpc_trace_headers"
+    ], 
     "headers": [
       "include/grpc/byte_buffer.h", 
       "include/grpc/byte_buffer_reader.h", 
@@ -7632,6 +7960,7 @@
       "src/core/lib/channel/handshaker_registry.h", 
       "src/core/lib/compression/algorithm_metadata.h", 
       "src/core/lib/compression/message_compress.h", 
+      "src/core/lib/compression/stream_compression.h", 
       "src/core/lib/http/format_request.h", 
       "src/core/lib/http/httpcli.h", 
       "src/core/lib/http/parser.h", 
@@ -7654,9 +7983,11 @@
       "src/core/lib/iomgr/iomgr.h", 
       "src/core/lib/iomgr/iomgr_internal.h", 
       "src/core/lib/iomgr/iomgr_posix.h", 
+      "src/core/lib/iomgr/iomgr_uv.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", 
@@ -7734,7 +8065,7 @@
     ], 
     "is_filegroup": true, 
     "language": "c", 
-    "name": "grpc_base", 
+    "name": "grpc_base_headers", 
     "src": [
       "include/grpc/byte_buffer.h", 
       "include/grpc/byte_buffer_reader.h", 
@@ -7747,239 +8078,118 @@
       "include/grpc/slice_buffer.h", 
       "include/grpc/status.h", 
       "include/grpc/support/workaround_list.h", 
-      "src/core/lib/channel/channel_args.c", 
       "src/core/lib/channel/channel_args.h", 
-      "src/core/lib/channel/channel_stack.c", 
       "src/core/lib/channel/channel_stack.h", 
-      "src/core/lib/channel/channel_stack_builder.c", 
       "src/core/lib/channel/channel_stack_builder.h", 
-      "src/core/lib/channel/connected_channel.c", 
       "src/core/lib/channel/connected_channel.h", 
       "src/core/lib/channel/context.h", 
-      "src/core/lib/channel/handshaker.c", 
       "src/core/lib/channel/handshaker.h", 
-      "src/core/lib/channel/handshaker_factory.c", 
       "src/core/lib/channel/handshaker_factory.h", 
-      "src/core/lib/channel/handshaker_registry.c", 
       "src/core/lib/channel/handshaker_registry.h", 
       "src/core/lib/compression/algorithm_metadata.h", 
-      "src/core/lib/compression/compression.c", 
-      "src/core/lib/compression/message_compress.c", 
       "src/core/lib/compression/message_compress.h", 
-      "src/core/lib/http/format_request.c", 
+      "src/core/lib/compression/stream_compression.h", 
       "src/core/lib/http/format_request.h", 
-      "src/core/lib/http/httpcli.c", 
       "src/core/lib/http/httpcli.h", 
-      "src/core/lib/http/parser.c", 
       "src/core/lib/http/parser.h", 
-      "src/core/lib/iomgr/closure.c", 
       "src/core/lib/iomgr/closure.h", 
-      "src/core/lib/iomgr/combiner.c", 
       "src/core/lib/iomgr/combiner.h", 
-      "src/core/lib/iomgr/endpoint.c", 
       "src/core/lib/iomgr/endpoint.h", 
       "src/core/lib/iomgr/endpoint_pair.h", 
-      "src/core/lib/iomgr/endpoint_pair_posix.c", 
-      "src/core/lib/iomgr/endpoint_pair_uv.c", 
-      "src/core/lib/iomgr/endpoint_pair_windows.c", 
-      "src/core/lib/iomgr/error.c", 
       "src/core/lib/iomgr/error.h", 
       "src/core/lib/iomgr/error_internal.h", 
-      "src/core/lib/iomgr/ev_epoll1_linux.c", 
       "src/core/lib/iomgr/ev_epoll1_linux.h", 
-      "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c", 
       "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h", 
-      "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c", 
       "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h", 
-      "src/core/lib/iomgr/ev_epollex_linux.c", 
       "src/core/lib/iomgr/ev_epollex_linux.h", 
-      "src/core/lib/iomgr/ev_epollsig_linux.c", 
       "src/core/lib/iomgr/ev_epollsig_linux.h", 
-      "src/core/lib/iomgr/ev_poll_posix.c", 
       "src/core/lib/iomgr/ev_poll_posix.h", 
-      "src/core/lib/iomgr/ev_posix.c", 
       "src/core/lib/iomgr/ev_posix.h", 
-      "src/core/lib/iomgr/ev_windows.c", 
-      "src/core/lib/iomgr/exec_ctx.c", 
       "src/core/lib/iomgr/exec_ctx.h", 
-      "src/core/lib/iomgr/executor.c", 
       "src/core/lib/iomgr/executor.h", 
-      "src/core/lib/iomgr/iocp_windows.c", 
       "src/core/lib/iomgr/iocp_windows.h", 
-      "src/core/lib/iomgr/iomgr.c", 
       "src/core/lib/iomgr/iomgr.h", 
       "src/core/lib/iomgr/iomgr_internal.h", 
-      "src/core/lib/iomgr/iomgr_posix.c", 
       "src/core/lib/iomgr/iomgr_posix.h", 
-      "src/core/lib/iomgr/iomgr_uv.c", 
-      "src/core/lib/iomgr/iomgr_windows.c", 
-      "src/core/lib/iomgr/is_epollexclusive_available.c", 
+      "src/core/lib/iomgr/iomgr_uv.h", 
       "src/core/lib/iomgr/is_epollexclusive_available.h", 
-      "src/core/lib/iomgr/load_file.c", 
       "src/core/lib/iomgr/load_file.h", 
-      "src/core/lib/iomgr/lockfree_event.c", 
       "src/core/lib/iomgr/lockfree_event.h", 
-      "src/core/lib/iomgr/network_status_tracker.c", 
+      "src/core/lib/iomgr/nameser.h", 
       "src/core/lib/iomgr/network_status_tracker.h", 
-      "src/core/lib/iomgr/polling_entity.c", 
       "src/core/lib/iomgr/polling_entity.h", 
       "src/core/lib/iomgr/pollset.h", 
       "src/core/lib/iomgr/pollset_set.h", 
-      "src/core/lib/iomgr/pollset_set_uv.c", 
-      "src/core/lib/iomgr/pollset_set_windows.c", 
       "src/core/lib/iomgr/pollset_set_windows.h", 
-      "src/core/lib/iomgr/pollset_uv.c", 
       "src/core/lib/iomgr/pollset_uv.h", 
-      "src/core/lib/iomgr/pollset_windows.c", 
       "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_posix.c", 
-      "src/core/lib/iomgr/resolve_address_uv.c", 
-      "src/core/lib/iomgr/resolve_address_windows.c", 
-      "src/core/lib/iomgr/resource_quota.c", 
       "src/core/lib/iomgr/resource_quota.h", 
       "src/core/lib/iomgr/sockaddr.h", 
       "src/core/lib/iomgr/sockaddr_posix.h", 
-      "src/core/lib/iomgr/sockaddr_utils.c", 
       "src/core/lib/iomgr/sockaddr_utils.h", 
       "src/core/lib/iomgr/sockaddr_windows.h", 
-      "src/core/lib/iomgr/socket_factory_posix.c", 
       "src/core/lib/iomgr/socket_factory_posix.h", 
-      "src/core/lib/iomgr/socket_mutator.c", 
       "src/core/lib/iomgr/socket_mutator.h", 
       "src/core/lib/iomgr/socket_utils.h", 
-      "src/core/lib/iomgr/socket_utils_common_posix.c", 
-      "src/core/lib/iomgr/socket_utils_linux.c", 
-      "src/core/lib/iomgr/socket_utils_posix.c", 
       "src/core/lib/iomgr/socket_utils_posix.h", 
-      "src/core/lib/iomgr/socket_utils_uv.c", 
-      "src/core/lib/iomgr/socket_utils_windows.c", 
-      "src/core/lib/iomgr/socket_windows.c", 
       "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.c", 
       "src/core/lib/iomgr/tcp_client_posix.h", 
-      "src/core/lib/iomgr/tcp_client_uv.c", 
-      "src/core/lib/iomgr/tcp_client_windows.c", 
-      "src/core/lib/iomgr/tcp_posix.c", 
       "src/core/lib/iomgr/tcp_posix.h", 
       "src/core/lib/iomgr/tcp_server.h", 
-      "src/core/lib/iomgr/tcp_server_posix.c", 
       "src/core/lib/iomgr/tcp_server_utils_posix.h", 
-      "src/core/lib/iomgr/tcp_server_utils_posix_common.c", 
-      "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", 
-      "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", 
-      "src/core/lib/iomgr/tcp_server_uv.c", 
-      "src/core/lib/iomgr/tcp_server_windows.c", 
-      "src/core/lib/iomgr/tcp_uv.c", 
       "src/core/lib/iomgr/tcp_uv.h", 
-      "src/core/lib/iomgr/tcp_windows.c", 
       "src/core/lib/iomgr/tcp_windows.h", 
-      "src/core/lib/iomgr/time_averaged_stats.c", 
       "src/core/lib/iomgr/time_averaged_stats.h", 
       "src/core/lib/iomgr/timer.h", 
-      "src/core/lib/iomgr/timer_generic.c", 
       "src/core/lib/iomgr/timer_generic.h", 
-      "src/core/lib/iomgr/timer_heap.c", 
       "src/core/lib/iomgr/timer_heap.h", 
-      "src/core/lib/iomgr/timer_manager.c", 
       "src/core/lib/iomgr/timer_manager.h", 
-      "src/core/lib/iomgr/timer_uv.c", 
       "src/core/lib/iomgr/timer_uv.h", 
-      "src/core/lib/iomgr/udp_server.c", 
       "src/core/lib/iomgr/udp_server.h", 
-      "src/core/lib/iomgr/unix_sockets_posix.c", 
       "src/core/lib/iomgr/unix_sockets_posix.h", 
-      "src/core/lib/iomgr/unix_sockets_posix_noop.c", 
-      "src/core/lib/iomgr/wakeup_fd_cv.c", 
       "src/core/lib/iomgr/wakeup_fd_cv.h", 
-      "src/core/lib/iomgr/wakeup_fd_eventfd.c", 
-      "src/core/lib/iomgr/wakeup_fd_nospecial.c", 
-      "src/core/lib/iomgr/wakeup_fd_pipe.c", 
       "src/core/lib/iomgr/wakeup_fd_pipe.h", 
-      "src/core/lib/iomgr/wakeup_fd_posix.c", 
       "src/core/lib/iomgr/wakeup_fd_posix.h", 
-      "src/core/lib/json/json.c", 
       "src/core/lib/json/json.h", 
       "src/core/lib/json/json_common.h", 
-      "src/core/lib/json/json_reader.c", 
       "src/core/lib/json/json_reader.h", 
-      "src/core/lib/json/json_string.c", 
-      "src/core/lib/json/json_writer.c", 
       "src/core/lib/json/json_writer.h", 
-      "src/core/lib/slice/b64.c", 
       "src/core/lib/slice/b64.h", 
-      "src/core/lib/slice/percent_encoding.c", 
       "src/core/lib/slice/percent_encoding.h", 
-      "src/core/lib/slice/slice.c", 
-      "src/core/lib/slice/slice_buffer.c", 
-      "src/core/lib/slice/slice_hash_table.c", 
       "src/core/lib/slice/slice_hash_table.h", 
-      "src/core/lib/slice/slice_intern.c", 
       "src/core/lib/slice/slice_internal.h", 
-      "src/core/lib/slice/slice_string_helpers.c", 
       "src/core/lib/slice/slice_string_helpers.h", 
-      "src/core/lib/surface/alarm.c", 
-      "src/core/lib/surface/api_trace.c", 
       "src/core/lib/surface/api_trace.h", 
-      "src/core/lib/surface/byte_buffer.c", 
-      "src/core/lib/surface/byte_buffer_reader.c", 
-      "src/core/lib/surface/call.c", 
       "src/core/lib/surface/call.h", 
-      "src/core/lib/surface/call_details.c", 
-      "src/core/lib/surface/call_log_batch.c", 
       "src/core/lib/surface/call_test_only.h", 
-      "src/core/lib/surface/channel.c", 
       "src/core/lib/surface/channel.h", 
-      "src/core/lib/surface/channel_init.c", 
       "src/core/lib/surface/channel_init.h", 
-      "src/core/lib/surface/channel_ping.c", 
-      "src/core/lib/surface/channel_stack_type.c", 
       "src/core/lib/surface/channel_stack_type.h", 
-      "src/core/lib/surface/completion_queue.c", 
       "src/core/lib/surface/completion_queue.h", 
-      "src/core/lib/surface/completion_queue_factory.c", 
       "src/core/lib/surface/completion_queue_factory.h", 
-      "src/core/lib/surface/event_string.c", 
       "src/core/lib/surface/event_string.h", 
       "src/core/lib/surface/init.h", 
-      "src/core/lib/surface/lame_client.cc", 
       "src/core/lib/surface/lame_client.h", 
-      "src/core/lib/surface/metadata_array.c", 
-      "src/core/lib/surface/server.c", 
       "src/core/lib/surface/server.h", 
-      "src/core/lib/surface/validate_metadata.c", 
       "src/core/lib/surface/validate_metadata.h", 
-      "src/core/lib/surface/version.c", 
-      "src/core/lib/transport/bdp_estimator.c", 
       "src/core/lib/transport/bdp_estimator.h", 
-      "src/core/lib/transport/byte_stream.c", 
       "src/core/lib/transport/byte_stream.h", 
-      "src/core/lib/transport/connectivity_state.c", 
       "src/core/lib/transport/connectivity_state.h", 
-      "src/core/lib/transport/error_utils.c", 
       "src/core/lib/transport/error_utils.h", 
       "src/core/lib/transport/http2_errors.h", 
-      "src/core/lib/transport/metadata.c", 
       "src/core/lib/transport/metadata.h", 
-      "src/core/lib/transport/metadata_batch.c", 
       "src/core/lib/transport/metadata_batch.h", 
-      "src/core/lib/transport/pid_controller.c", 
       "src/core/lib/transport/pid_controller.h", 
-      "src/core/lib/transport/service_config.c", 
       "src/core/lib/transport/service_config.h", 
-      "src/core/lib/transport/static_metadata.c", 
       "src/core/lib/transport/static_metadata.h", 
-      "src/core/lib/transport/status_conversion.c", 
       "src/core/lib/transport/status_conversion.h", 
-      "src/core/lib/transport/timeout_encoding.c", 
       "src/core/lib/transport/timeout_encoding.h", 
-      "src/core/lib/transport/transport.c", 
       "src/core/lib/transport/transport.h", 
-      "src/core/lib/transport/transport_impl.h", 
-      "src/core/lib/transport/transport_op_string.c"
+      "src/core/lib/transport/transport_impl.h"
     ], 
     "third_party": false, 
     "type": "filegroup"
@@ -8467,8 +8677,11 @@
   }, 
   {
     "deps": [
+      "gpr", 
       "gpr_test_util", 
-      "grpc"
+      "grpc_base", 
+      "grpc_client_channel", 
+      "grpc_transport_chttp2"
     ], 
     "headers": [
       "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h", 
@@ -8527,6 +8740,21 @@
   }, 
   {
     "deps": [
+      "gpr", 
+      "grpc_trace_headers"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_trace", 
+    "src": [
+      "src/core/lib/debug/trace.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
       "gpr"
     ], 
     "headers": [
@@ -8534,9 +8762,8 @@
     ], 
     "is_filegroup": true, 
     "language": "c", 
-    "name": "grpc_trace", 
+    "name": "grpc_trace_headers", 
     "src": [
-      "src/core/lib/debug/trace.c", 
       "src/core/lib/debug/trace.h"
     ], 
     "third_party": false, 
@@ -8581,6 +8808,7 @@
       "src/core/ext/transport/chttp2/transport/chttp2_plugin.c", 
       "src/core/ext/transport/chttp2/transport/chttp2_transport.c", 
       "src/core/ext/transport/chttp2/transport/chttp2_transport.h", 
+      "src/core/ext/transport/chttp2/transport/flow_control.c", 
       "src/core/ext/transport/chttp2/transport/frame.h", 
       "src/core/ext/transport/chttp2/transport/frame_data.c", 
       "src/core/ext/transport/chttp2/transport/frame_data.h", 
@@ -8780,6 +9008,40 @@
     "deps": [
       "gpr", 
       "grpc_base", 
+      "grpc_transport_inproc_headers"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_transport_inproc", 
+    "src": [
+      "src/core/ext/transport/inproc/inproc_plugin.c", 
+      "src/core/ext/transport/inproc/inproc_transport.c"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base_headers"
+    ], 
+    "headers": [
+      "src/core/ext/transport/inproc/inproc_transport.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_transport_inproc_headers", 
+    "src": [
+      "src/core/ext/transport/inproc/inproc_transport.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
       "grpc_server_backward_compatibility"
     ], 
     "headers": [
@@ -8796,6 +9058,18 @@
     "type": "filegroup"
   }, 
   {
+    "deps": [
+      "nanopb_headers"
+    ], 
+    "headers": [], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "nanopb", 
+    "src": [], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
     "deps": [], 
     "headers": [
       "third_party/nanopb/pb.h", 
@@ -8805,7 +9079,7 @@
     ], 
     "is_filegroup": true, 
     "language": "c", 
-    "name": "nanopb", 
+    "name": "nanopb_headers", 
     "src": [], 
     "third_party": false, 
     "type": "filegroup"
@@ -8813,10 +9087,12 @@
   {
     "deps": [
       "gpr", 
+      "grpc_base", 
       "grpc_trace"
     ], 
     "headers": [
       "src/core/tsi/fake_transport_security.h", 
+      "src/core/tsi/gts_transport_security.h", 
       "src/core/tsi/ssl_transport_security.h", 
       "src/core/tsi/ssl_types.h", 
       "src/core/tsi/transport_security.h", 
@@ -8829,6 +9105,8 @@
     "src": [
       "src/core/tsi/fake_transport_security.c", 
       "src/core/tsi/fake_transport_security.h", 
+      "src/core/tsi/gts_transport_security.c", 
+      "src/core/tsi/gts_transport_security.h", 
       "src/core/tsi/ssl_transport_security.c", 
       "src/core/tsi/ssl_transport_security.h", 
       "src/core/tsi/ssl_types.h", 
@@ -8843,159 +9121,6 @@
   }, 
   {
     "deps": [
-      "grpc", 
-      "grpc++_codegen_base", 
-      "nanopb"
-    ], 
-    "headers": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/create_channel_posix.h", 
-      "include/grpc++/ext/health_check_service_server_builder_option.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/health_check_service_interface.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/channel_argument_option.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/core_codegen.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/server_builder_plugin.h", 
-      "include/grpc++/impl/server_initializer.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/resource_quota.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/server_posix.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/create_channel_internal.h", 
-      "src/cpp/common/channel_filter.h", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/health/default_health_check_service.h", 
-      "src/cpp/server/health/health.pb.h", 
-      "src/cpp/server/thread_pool_interface.h", 
-      "src/cpp/thread_manager/thread_manager.h"
-    ], 
-    "is_filegroup": true, 
-    "language": "c++", 
-    "name": "grpc++_base", 
-    "src": [
-      "include/grpc++/alarm.h", 
-      "include/grpc++/channel.h", 
-      "include/grpc++/client_context.h", 
-      "include/grpc++/completion_queue.h", 
-      "include/grpc++/create_channel.h", 
-      "include/grpc++/create_channel_posix.h", 
-      "include/grpc++/ext/health_check_service_server_builder_option.h", 
-      "include/grpc++/generic/async_generic_service.h", 
-      "include/grpc++/generic/generic_stub.h", 
-      "include/grpc++/grpc++.h", 
-      "include/grpc++/health_check_service_interface.h", 
-      "include/grpc++/impl/call.h", 
-      "include/grpc++/impl/channel_argument_option.h", 
-      "include/grpc++/impl/client_unary_call.h", 
-      "include/grpc++/impl/codegen/core_codegen.h", 
-      "include/grpc++/impl/grpc_library.h", 
-      "include/grpc++/impl/method_handler_impl.h", 
-      "include/grpc++/impl/rpc_method.h", 
-      "include/grpc++/impl/rpc_service_method.h", 
-      "include/grpc++/impl/serialization_traits.h", 
-      "include/grpc++/impl/server_builder_option.h", 
-      "include/grpc++/impl/server_builder_plugin.h", 
-      "include/grpc++/impl/server_initializer.h", 
-      "include/grpc++/impl/service_type.h", 
-      "include/grpc++/resource_quota.h", 
-      "include/grpc++/security/auth_context.h", 
-      "include/grpc++/security/auth_metadata_processor.h", 
-      "include/grpc++/security/credentials.h", 
-      "include/grpc++/security/server_credentials.h", 
-      "include/grpc++/server.h", 
-      "include/grpc++/server_builder.h", 
-      "include/grpc++/server_context.h", 
-      "include/grpc++/server_posix.h", 
-      "include/grpc++/support/async_stream.h", 
-      "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/byte_buffer.h", 
-      "include/grpc++/support/channel_arguments.h", 
-      "include/grpc++/support/config.h", 
-      "include/grpc++/support/slice.h", 
-      "include/grpc++/support/status.h", 
-      "include/grpc++/support/status_code_enum.h", 
-      "include/grpc++/support/string_ref.h", 
-      "include/grpc++/support/stub_options.h", 
-      "include/grpc++/support/sync_stream.h", 
-      "include/grpc++/support/time.h", 
-      "src/cpp/client/channel_cc.cc", 
-      "src/cpp/client/client_context.cc", 
-      "src/cpp/client/create_channel.cc", 
-      "src/cpp/client/create_channel_internal.cc", 
-      "src/cpp/client/create_channel_internal.h", 
-      "src/cpp/client/create_channel_posix.cc", 
-      "src/cpp/client/credentials_cc.cc", 
-      "src/cpp/client/generic_stub.cc", 
-      "src/cpp/common/channel_arguments.cc", 
-      "src/cpp/common/channel_filter.cc", 
-      "src/cpp/common/channel_filter.h", 
-      "src/cpp/common/completion_queue_cc.cc", 
-      "src/cpp/common/core_codegen.cc", 
-      "src/cpp/common/resource_quota_cc.cc", 
-      "src/cpp/common/rpc_method.cc", 
-      "src/cpp/common/version_cc.cc", 
-      "src/cpp/server/async_generic_service.cc", 
-      "src/cpp/server/channel_argument_option.cc", 
-      "src/cpp/server/create_default_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.cc", 
-      "src/cpp/server/dynamic_thread_pool.h", 
-      "src/cpp/server/health/default_health_check_service.cc", 
-      "src/cpp/server/health/default_health_check_service.h", 
-      "src/cpp/server/health/health.pb.c", 
-      "src/cpp/server/health/health.pb.h", 
-      "src/cpp/server/health/health_check_service.cc", 
-      "src/cpp/server/health/health_check_service_server_builder_option.cc", 
-      "src/cpp/server/server_builder.cc", 
-      "src/cpp/server/server_cc.cc", 
-      "src/cpp/server/server_context.cc", 
-      "src/cpp/server/server_credentials.cc", 
-      "src/cpp/server/server_posix.cc", 
-      "src/cpp/server/thread_pool_interface.h", 
-      "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"
-    ], 
-    "third_party": false, 
-    "type": "filegroup"
-  }, 
-  {
-    "deps": [
       "grpc_codegen"
     ], 
     "headers": [
@@ -9098,6 +9223,162 @@
     "type": "filegroup"
   }, 
   {
+    "deps": [
+      "gpr", 
+      "gpr_base_headers", 
+      "grpc++_codegen_base", 
+      "grpc_base_headers", 
+      "grpc_transport_inproc_headers", 
+      "nanopb_headers"
+    ], 
+    "headers": [
+      "include/grpc++/alarm.h", 
+      "include/grpc++/channel.h", 
+      "include/grpc++/client_context.h", 
+      "include/grpc++/completion_queue.h", 
+      "include/grpc++/create_channel.h", 
+      "include/grpc++/create_channel_posix.h", 
+      "include/grpc++/ext/health_check_service_server_builder_option.h", 
+      "include/grpc++/generic/async_generic_service.h", 
+      "include/grpc++/generic/generic_stub.h", 
+      "include/grpc++/grpc++.h", 
+      "include/grpc++/health_check_service_interface.h", 
+      "include/grpc++/impl/call.h", 
+      "include/grpc++/impl/channel_argument_option.h", 
+      "include/grpc++/impl/client_unary_call.h", 
+      "include/grpc++/impl/codegen/core_codegen.h", 
+      "include/grpc++/impl/grpc_library.h", 
+      "include/grpc++/impl/method_handler_impl.h", 
+      "include/grpc++/impl/rpc_method.h", 
+      "include/grpc++/impl/rpc_service_method.h", 
+      "include/grpc++/impl/serialization_traits.h", 
+      "include/grpc++/impl/server_builder_option.h", 
+      "include/grpc++/impl/server_builder_plugin.h", 
+      "include/grpc++/impl/server_initializer.h", 
+      "include/grpc++/impl/service_type.h", 
+      "include/grpc++/resource_quota.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
+      "include/grpc++/server.h", 
+      "include/grpc++/server_builder.h", 
+      "include/grpc++/server_context.h", 
+      "include/grpc++/server_posix.h", 
+      "include/grpc++/support/async_stream.h", 
+      "include/grpc++/support/async_unary_call.h", 
+      "include/grpc++/support/byte_buffer.h", 
+      "include/grpc++/support/channel_arguments.h", 
+      "include/grpc++/support/config.h", 
+      "include/grpc++/support/slice.h", 
+      "include/grpc++/support/status.h", 
+      "include/grpc++/support/status_code_enum.h", 
+      "include/grpc++/support/string_ref.h", 
+      "include/grpc++/support/stub_options.h", 
+      "include/grpc++/support/sync_stream.h", 
+      "include/grpc++/support/time.h", 
+      "src/cpp/client/create_channel_internal.h", 
+      "src/cpp/common/channel_filter.h", 
+      "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/health/default_health_check_service.h", 
+      "src/cpp/server/health/health.pb.h", 
+      "src/cpp/server/thread_pool_interface.h", 
+      "src/cpp/thread_manager/thread_manager.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c++", 
+    "name": "grpc++_common", 
+    "src": [
+      "include/grpc++/alarm.h", 
+      "include/grpc++/channel.h", 
+      "include/grpc++/client_context.h", 
+      "include/grpc++/completion_queue.h", 
+      "include/grpc++/create_channel.h", 
+      "include/grpc++/create_channel_posix.h", 
+      "include/grpc++/ext/health_check_service_server_builder_option.h", 
+      "include/grpc++/generic/async_generic_service.h", 
+      "include/grpc++/generic/generic_stub.h", 
+      "include/grpc++/grpc++.h", 
+      "include/grpc++/health_check_service_interface.h", 
+      "include/grpc++/impl/call.h", 
+      "include/grpc++/impl/channel_argument_option.h", 
+      "include/grpc++/impl/client_unary_call.h", 
+      "include/grpc++/impl/codegen/core_codegen.h", 
+      "include/grpc++/impl/grpc_library.h", 
+      "include/grpc++/impl/method_handler_impl.h", 
+      "include/grpc++/impl/rpc_method.h", 
+      "include/grpc++/impl/rpc_service_method.h", 
+      "include/grpc++/impl/serialization_traits.h", 
+      "include/grpc++/impl/server_builder_option.h", 
+      "include/grpc++/impl/server_builder_plugin.h", 
+      "include/grpc++/impl/server_initializer.h", 
+      "include/grpc++/impl/service_type.h", 
+      "include/grpc++/resource_quota.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
+      "include/grpc++/server.h", 
+      "include/grpc++/server_builder.h", 
+      "include/grpc++/server_context.h", 
+      "include/grpc++/server_posix.h", 
+      "include/grpc++/support/async_stream.h", 
+      "include/grpc++/support/async_unary_call.h", 
+      "include/grpc++/support/byte_buffer.h", 
+      "include/grpc++/support/channel_arguments.h", 
+      "include/grpc++/support/config.h", 
+      "include/grpc++/support/slice.h", 
+      "include/grpc++/support/status.h", 
+      "include/grpc++/support/status_code_enum.h", 
+      "include/grpc++/support/string_ref.h", 
+      "include/grpc++/support/stub_options.h", 
+      "include/grpc++/support/sync_stream.h", 
+      "include/grpc++/support/time.h", 
+      "src/cpp/client/channel_cc.cc", 
+      "src/cpp/client/client_context.cc", 
+      "src/cpp/client/create_channel.cc", 
+      "src/cpp/client/create_channel_internal.cc", 
+      "src/cpp/client/create_channel_internal.h", 
+      "src/cpp/client/create_channel_posix.cc", 
+      "src/cpp/client/credentials_cc.cc", 
+      "src/cpp/client/generic_stub.cc", 
+      "src/cpp/common/channel_arguments.cc", 
+      "src/cpp/common/channel_filter.cc", 
+      "src/cpp/common/channel_filter.h", 
+      "src/cpp/common/completion_queue_cc.cc", 
+      "src/cpp/common/core_codegen.cc", 
+      "src/cpp/common/resource_quota_cc.cc", 
+      "src/cpp/common/rpc_method.cc", 
+      "src/cpp/common/version_cc.cc", 
+      "src/cpp/server/async_generic_service.cc", 
+      "src/cpp/server/channel_argument_option.cc", 
+      "src/cpp/server/create_default_thread_pool.cc", 
+      "src/cpp/server/dynamic_thread_pool.cc", 
+      "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/health/default_health_check_service.cc", 
+      "src/cpp/server/health/default_health_check_service.h", 
+      "src/cpp/server/health/health.pb.c", 
+      "src/cpp/server/health/health.pb.h", 
+      "src/cpp/server/health/health_check_service.cc", 
+      "src/cpp/server/health/health_check_service_server_builder_option.cc", 
+      "src/cpp/server/server_builder.cc", 
+      "src/cpp/server/server_cc.cc", 
+      "src/cpp/server/server_context.cc", 
+      "src/cpp/server/server_credentials.cc", 
+      "src/cpp/server/server_posix.cc", 
+      "src/cpp/server/thread_pool_interface.h", 
+      "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"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
     "deps": [], 
     "headers": [
       "include/grpc++/impl/codegen/config_protobuf.h"
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index dd81241..be8a0ef 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -215,6 +215,28 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "byte_stream_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "census_context_test", 
     "platforms": [
       "linux", 
@@ -1390,7 +1412,9 @@
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
-    "exclude_iomgrs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
@@ -2285,6 +2309,28 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "stream_compression_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "stream_owned_slice_test", 
     "platforms": [
       "linux", 
@@ -3855,6 +3901,28 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "server_request_call_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
     "name": "shutdown_test", 
     "platforms": [
       "linux", 
@@ -3947,7 +4015,8 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "timeout_seconds": 1200
   }, 
   {
     "args": [], 
@@ -16307,6 +16376,30 @@
   }, 
   {
     "args": [
+      "proxy_auth"
+    ], 
+    "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": [
       "registered_call"
     ], 
     "ci_platforms": [
@@ -28687,6 +28780,972 @@
     "exclude_iomgrs": [], 
     "flaky": false, 
     "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "binary_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "call_creds"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_accept"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_client_done"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_invoke"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_round_trip"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_before_invoke"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_in_a_vacuum"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_with_status"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "empty_batch"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_latency"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "high_initial_seqno"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "hpack_size"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "invoke_large_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "large_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "load_reporting_hook"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "max_message_length"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "negative_deadline"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "network_status_change"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "no_logging"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "no_op"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "payload"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "ping_pong_streaming"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "registered_call"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "request_with_flags"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "request_with_payload"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "resource_quota_server"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "server_finishes_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "shutdown_finishes_calls"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "shutdown_finishes_tags"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_cacheable_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "streaming_error_response"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "trailing_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "workaround_cronet_compression"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "write_buffering"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "write_buffering_at_end"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "authority_not_supported"
+    ], 
+    "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", 
@@ -37854,6 +38913,30 @@
   }, 
   {
     "args": [
+      "proxy_auth"
+    ], 
+    "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": [
       "registered_call"
     ], 
     "ci_platforms": [
@@ -45139,6 +46222,949 @@
   }, 
   {
     "args": [
+      "authority_not_supported"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "binary_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_accept"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_client_done"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_invoke"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_after_round_trip"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_before_invoke"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_in_a_vacuum"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "cancel_with_status"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "empty_batch"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_causes_close"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "filter_latency"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "high_initial_seqno"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "hpack_size"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "idempotent_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "invoke_large_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "large_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "load_reporting_hook"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "max_message_length"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "negative_deadline"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "network_status_change"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "no_logging"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "no_op"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "payload"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "ping_pong_streaming"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "registered_call"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "request_with_flags"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "request_with_payload"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "resource_quota_server"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "server_finishes_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "shutdown_finishes_calls"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "shutdown_finishes_tags"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_cacheable_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "simple_request"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "streaming_error_response"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "trailing_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "workaround_cronet_compression"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "write_buffering"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "write_buffering_at_end"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "inproc_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
@@ -46069,7 +48095,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46094,7 +48120,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46119,7 +48145,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46144,7 +48170,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46169,7 +48195,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46269,7 +48295,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46294,7 +48320,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46321,7 +48347,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46346,7 +48372,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46373,7 +48399,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46398,7 +48424,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46423,7 +48449,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46448,7 +48474,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46473,7 +48499,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46498,7 +48524,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46523,7 +48549,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46548,7 +48574,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46573,7 +48599,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46598,7 +48624,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46623,7 +48649,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46648,7 +48674,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46673,7 +48699,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46698,7 +48724,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46723,7 +48749,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46748,7 +48774,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46773,7 +48799,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46798,7 +48824,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46823,7 +48849,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46848,7 +48874,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -46873,7 +48899,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48308,7 +50334,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48346,7 +50372,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48384,7 +50410,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48422,7 +50448,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48460,7 +50486,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48612,7 +50638,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48650,7 +50676,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48690,7 +50716,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48728,7 +50754,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48768,7 +50794,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48806,7 +50832,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48844,7 +50870,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48882,7 +50908,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48920,7 +50946,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48958,7 +50984,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -48996,7 +51022,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49034,7 +51060,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49072,7 +51098,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49110,7 +51136,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49148,7 +51174,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49186,7 +51212,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49224,7 +51250,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49262,7 +51288,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49300,7 +51326,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49338,7 +51364,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49376,7 +51402,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49414,7 +51440,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49452,7 +51478,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49490,7 +51516,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -49528,7 +51554,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -90712,6 +92738,29 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984"
+    ], 
+    "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-5175380371570688"
     ], 
     "ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/build_python.sh b/tools/run_tests/helper_scripts/build_python.sh
index 1c1034e..be65055 100755
--- a/tools/run_tests/helper_scripts/build_python.sh
+++ b/tools/run_tests/helper_scripts/build_python.sh
@@ -171,6 +171,9 @@
 $VENV_PYTHON $ROOT/src/python/grpcio_reflection/setup.py build_package_protos
 pip_install_dir $ROOT/src/python/grpcio_reflection
 
+# Install testing
+pip_install_dir $ROOT/src/python/grpcio_testing
+
 # Build/install tests
 $VENV_PYTHON -m pip install coverage==4.4 oauth2client==4.1.0 \
                             google-auth==1.0.0 requests==2.14.2
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
index 2177229..8868f40 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -82,6 +82,18 @@
         r['simple_params'] = sizes
     return r
 
+def _add_channel_arg(config, key, value):
+  if 'channel_args' in config:
+    channel_args = config['channel_args']
+  else:
+    channel_args = []
+    config['channel_args'] = channel_args
+  arg = {'name': key}
+  if isinstance(value, int):
+    arg['int_value'] = value
+  else:
+    arg['str_value'] = value
+  channel_args.append(arg)
 
 def _ping_pong_scenario(name, rpc_type,
                         client_type, server_type,
@@ -102,7 +114,8 @@
                         num_clients=None,
                         resource_quota_size=None,
                         messages_per_stream=None,
-                        excluded_poll_engines=[]):
+                        excluded_poll_engines=[],
+                        minimal_stack=False):
   """Creates a basic ping pong scenario."""
   scenario = {
     'name': name,
@@ -170,6 +183,10 @@
   scenario['client_config']['channel_args'].append(optimization_channel_arg)
   scenario['server_config']['channel_args'].append(optimization_channel_arg)
 
+  if minimal_stack:
+    _add_channel_arg(scenario['client_config'], 'grpc.minimal_stack', 1)
+    _add_channel_arg(scenario['server_config'], 'grpc.minimal_stack', 1)
+
   if messages_per_stream:
     scenario['client_config']['messages_per_stream'] = messages_per_stream
   if client_language:
@@ -237,6 +254,7 @@
           server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories+[SCALABLE])
 
       for mps in geometric_progression(1, 20, 10):
@@ -247,6 +265,7 @@
             server_type='ASYNC_GENERIC_SERVER',
             unconstrained_client='async', use_generic_payload=True,
             secure=secure, messages_per_stream=mps,
+            minimal_stack=not secure,
             categories=smoketest_categories+[SCALABLE])
 
       for mps in geometric_progression(1, 200, math.sqrt(10)):
@@ -257,6 +276,7 @@
             server_type='ASYNC_GENERIC_SERVER',
             unconstrained_client='async', use_generic_payload=True,
             secure=secure, messages_per_stream=mps,
+            minimal_stack=not secure,
             categories=[SWEEP])
 
       yield _ping_pong_scenario(
@@ -268,6 +288,7 @@
           server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories+[SCALABLE],
           channels=1, outstanding=100)
 
@@ -280,6 +301,7 @@
           server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories+[SCALABLE])
 
       # TODO(https://github.com/grpc/grpc/issues/11500) Re-enable this test
@@ -350,6 +372,7 @@
           server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async-limited', use_generic_payload=True,
           async_server_threads=1,
+          minimal_stack=not secure,
           secure=secure)
 
       yield _ping_pong_scenario(
@@ -360,6 +383,7 @@
           server_type='SYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories + [SCALABLE],
           excluded_poll_engines = ['poll-cv'])
 
@@ -374,6 +398,7 @@
           req_size=128,
           resp_size=8*1024*1024,
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories + [SCALABLE])
 
       yield _ping_pong_scenario(
@@ -383,6 +408,7 @@
           server_type='SYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
+          minimal_stack=not secure,
           categories=smoketest_categories+[SCALABLE],
           excluded_poll_engines = ['poll-cv'])
 
@@ -391,6 +417,7 @@
         client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
         req_size=1024*1024, resp_size=1024*1024,
         secure=secure,
+        minimal_stack=not secure,
         categories=smoketest_categories + [SCALABLE])
 
       for rpc_type in ['unary', 'streaming', 'streaming_from_client', 'streaming_from_server']:
@@ -401,6 +428,7 @@
               client_type='%s_CLIENT' % synchronicity.upper(),
               server_type='%s_SERVER' % synchronicity.upper(),
               async_server_threads=1,
+              minimal_stack=not secure,
               secure=secure)
 
           for size in geometric_progression(1, 1024*1024*1024+1, 8):
@@ -413,6 +441,7 @@
                   server_type='%s_SERVER' % synchronicity.upper(),
                   unconstrained_client=synchronicity,
                   secure=secure,
+                  minimal_stack=not secure,
                   categories=[SWEEP])
 
           yield _ping_pong_scenario(
@@ -422,6 +451,7 @@
               server_type='%s_SERVER' % synchronicity.upper(),
               unconstrained_client=synchronicity,
               secure=secure,
+              minimal_stack=not secure,
               categories=smoketest_categories+[SCALABLE])
 
           # TODO(vjpai): Re-enable this test. It has a lot of timeouts
@@ -446,6 +476,7 @@
                   server_type='%s_SERVER' % synchronicity.upper(),
                   unconstrained_client=synchronicity,
                   secure=secure, messages_per_stream=mps,
+                  minimal_stack=not secure,
                   categories=smoketest_categories+[SCALABLE])
 
             for mps in geometric_progression(1, 200, math.sqrt(10)):
@@ -456,6 +487,7 @@
                   server_type='%s_SERVER' % synchronicity.upper(),
                   unconstrained_client=synchronicity,
                   secure=secure, messages_per_stream=mps,
+                  minimal_stack=not secure,
                   categories=[SWEEP])
 
           for channels in geometric_progression(1, 20000, math.sqrt(10)):
@@ -468,6 +500,7 @@
                     client_type='%s_CLIENT' % synchronicity.upper(),
                     server_type='%s_SERVER' % synchronicity.upper(),
                     unconstrained_client=synchronicity, secure=secure,
+                    minimal_stack=not secure,
                     categories=[SWEEP], channels=channels, outstanding=outstanding)
 
   def __str__(self):
diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json
index 245861f..d7e2e29 100644
--- a/tools/run_tests/performance/scenario_result_schema.json
+++ b/tools/run_tests/performance/scenario_result_schema.json
@@ -216,6 +216,16 @@
         "name": "serverPollsPerRequest",
         "type": "FLOAT",
         "mode": "NULLABLE"
+      },
+      {
+        "name": "serverQueriesPerCpuSec",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "clientQueriesPerCpuSec",
+        "type": "FLOAT",
+        "mode": "NULLABLE"
       }
     ]
   },
diff --git a/tools/run_tests/python_utils/check_bazel_dir.py b/tools/run_tests/python_utils/check_bazel_dir.py
deleted file mode 100755
index 1daf6ee..0000000
--- a/tools/run_tests/python_utils/check_bazel_dir.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/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.
-
-"""This sends out a warning if any changes to the bazel dir are made."""
-
-from __future__ import print_function
-from subprocess import check_output
-
-import comment_on_pr
-import os
-
-_WARNING_MESSAGE = 'WARNING: You are making changes in the Bazel subdirectory. ' \
-                   'Please get explicit approval from @nicolasnoble before merging.'
-
-
-def _get_changed_files(base_branch):
-  """
-  Get list of changed files between current branch and base of target merge branch
-  """
-  # Get file changes between branch and merge-base of specified branch
-  base_commit = check_output(["git", "merge-base", base_branch, "HEAD"]).rstrip()
-  return check_output(["git", "diff", base_commit, "--name-only"]).splitlines()
-
-
-# ghprbTargetBranch environment variable only available during a Jenkins PR tests
-if 'ghprbTargetBranch' in os.environ:
-  changed_files = _get_changed_files('origin/%s' % os.environ['ghprbTargetBranch'])
-  if any(file.startswith('bazel/') for file in changed_files):
-    comment_on_pr.comment_on_pr(_WARNING_MESSAGE)
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 1e702a8..dbbf2ad 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -185,7 +185,7 @@
     return {}
 
   def unimplemented_test_cases(self):
-    return _SKIP_COMPRESSION
+    return []
 
   def unimplemented_test_cases_server(self):
     return _SKIP_COMPRESSION
@@ -210,7 +210,7 @@
     return {}
 
   def unimplemented_test_cases(self):
-    return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING
+    return _SKIP_DATA_FRAME_PADDING
 
   def __str__(self):
     return 'javaokhttp'
@@ -1230,6 +1230,11 @@
       _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:
+    sys.exit(0)
 except Exception as e:
   print('exception occurred:')
   traceback.print_exc(file=sys.stdout)
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 611868c..50eed62 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -245,7 +245,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 '
+      cflags = '-DGRPC_UV -DGRPC_UV_THREAD_CHECK'
       try:
         cflags += subprocess.check_output(['pkg-config', '--cflags', 'libuv']).strip() + ' '
       except (subprocess.CalledProcessError, OSError):
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 635d87f..6fe1609 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -126,23 +126,37 @@
   test_jobs += _generate_jobs(languages=['sanity', 'php7'],
                              configs=['dbg', 'opt'],
                              platforms=['linux'],
-                             labels=['basictests'],
+                             labels=['basictests', 'multilang'],
                              extra_args=extra_args,
                              inner_jobs=inner_jobs)
 
   # supported on all platforms.
-  test_jobs += _generate_jobs(languages=['c', 'csharp', 'node', 'python'],
+  test_jobs += _generate_jobs(languages=['c'],
                              configs=['dbg', 'opt'],
                              platforms=['linux', 'macos', 'windows'],
-                             labels=['basictests'],
+                             labels=['basictests', 'corelang'],
+                             extra_args=extra_args,
+                             inner_jobs=inner_jobs)
+  
+  test_jobs += _generate_jobs(languages=['csharp', 'node', 'python'],
+                             configs=['dbg', 'opt'],
+                             platforms=['linux', 'macos', 'windows'],
+                             labels=['basictests', 'multilang'],
                              extra_args=extra_args,
                              inner_jobs=inner_jobs)
 
   # supported on linux and mac.
-  test_jobs += _generate_jobs(languages=['c++', 'ruby', 'php'],
+  test_jobs += _generate_jobs(languages=['c++'],
                               configs=['dbg', 'opt'],
                               platforms=['linux', 'macos'],
-                              labels=['basictests'],
+                              labels=['basictests', 'corelang'],
+                              extra_args=extra_args,
+                              inner_jobs=inner_jobs)
+  
+  test_jobs += _generate_jobs(languages=['ruby', 'php'],
+                              configs=['dbg', 'opt'],
+                              platforms=['linux', 'macos'],
+                              labels=['basictests', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -150,7 +164,7 @@
   test_jobs += _generate_jobs(languages=['objc'],
                               configs=['dbg', 'opt'],
                               platforms=['macos'],
-                              labels=['basictests'],
+                              labels=['basictests', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -158,13 +172,13 @@
   test_jobs += _generate_jobs(languages=['c'],
                               configs=['msan', 'asan', 'tsan', 'ubsan'],
                               platforms=['linux'],
-                              labels=['sanitizers'],
+                              labels=['sanitizers', 'corelang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
   test_jobs += _generate_jobs(languages=['c++'],
                               configs=['asan', 'tsan'],
                               platforms=['linux'],
-                              labels=['sanitizers'],
+                              labels=['sanitizers', 'corelang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -179,7 +193,7 @@
                               platforms=['linux'],
                               arch='x86',
                               compiler='default',
-                              labels=['portability'],
+                              labels=['portability', 'corelang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -191,7 +205,7 @@
                                 platforms=['linux'],
                                 arch='x64',
                                 compiler=compiler,
-                                labels=['portability'],
+                                labels=['portability', 'corelang'],
                                 extra_args=extra_args,
                                 inner_jobs=inner_jobs)
 
@@ -203,14 +217,14 @@
                                   platforms=['windows'],
                                   arch=arch,
                                   compiler=compiler,
-                                  labels=['portability'],
+                                  labels=['portability', 'corelang'],
                                   extra_args=extra_args,
                                   inner_jobs=inner_jobs)
 
   # C and C++ with the c-ares DNS resolver on Linux
   test_jobs += _generate_jobs(languages=['c', 'c++'],
                               configs=['dbg'], platforms=['linux'],
-                              labels=['portability'],
+                              labels=['portability', 'corelang'],
                               extra_args=extra_args,
                               extra_envs={'GRPC_DNS_RESOLVER': 'ares'})
 
@@ -218,7 +232,7 @@
   # C with the c-ares DNS resolver on Windonws
   # test_jobs += _generate_jobs(languages=['c'],
   #                             configs=['dbg'], platforms=['windows'],
-  #                             labels=['portability'],
+  #                             labels=['portability', 'corelang'],
   #                             extra_args=extra_args,
   #                             extra_envs={'GRPC_DNS_RESOLVER': 'ares'})
 
@@ -230,7 +244,7 @@
                               platforms=['linux', 'windows'],
                               arch='default',
                               compiler='cmake',
-                              labels=['portability'],
+                              labels=['portability', 'corelang'],
                               extra_args=extra_args + ['--build_only'],
                               inner_jobs=inner_jobs)
 
@@ -239,7 +253,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='python_alpine',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -248,7 +262,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='coreclr',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -256,7 +270,7 @@
                               configs=['dbg'],
                               platforms=['linux'],
                               iomgr_platform='uv',
-                              labels=['portability'],
+                              labels=['portability', 'corelang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -265,7 +279,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='electron1.6',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -274,7 +288,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='node4',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -283,7 +297,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='node6',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
@@ -292,7 +306,7 @@
                               platforms=['linux'],
                               arch='default',
                               compiler='node7',
-                              labels=['portability'],
+                              labels=['portability', 'multilang'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)
 
diff --git a/tools/internal_ci/windows/grpc_master.cfg b/tools/run_tests/sanity/check_owners.sh
old mode 100644
new mode 100755
similarity index 68%
copy from tools/internal_ci/windows/grpc_master.cfg
copy to tools/run_tests/sanity/check_owners.sh
index 80abea6..b681fed
--- a/tools/internal_ci/windows/grpc_master.cfg
+++ b/tools/run_tests/sanity/check_owners.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 # Copyright 2017 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Config file for the internal CI (in protobuf text format)
 
-# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/windows/grpc_master.bat"
-timeout_mins: 360
-action {
-  define_artifacts {
-    regex: "**/*sponge_log.xml"
-  }
-}
+set -e
+
+export TEST=true
+
+cd `dirname $0`/../../..
+
+owners=.github/CODEOWNERS
+want_owners=`mktemp /tmp/submXXXXXX`
+
+tools/mkowners/mkowners.py -o $want_owners
+diff -u $owners $want_owners
+
+rm $want_owners
diff --git a/tools/run_tests/sanity/check_tracer_sanity.py b/tools/run_tests/sanity/check_tracer_sanity.py
new file mode 100755
index 0000000..997ec79
--- /dev/null
+++ b/tools/run_tests/sanity/check_tracer_sanity.py
@@ -0,0 +1,46 @@
+#!/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.
+
+from __future__ import print_function
+
+import os
+import sys
+import re
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
+
+errors = 0
+tracers = []
+pattern = re.compile("GRPC_TRACER_INITIALIZER\((true|false), \"(.*)\"\)")
+for root, dirs, files in os.walk('src/core'):
+  for filename in files:
+    path = os.path.join(root, filename)
+    if os.path.splitext(path)[1] != '.c': continue
+    with open(path) as f:
+      text = f.read()
+    for o in pattern.findall(text):
+      tracers.append(o[1])
+
+with open('doc/environment_variables.md') as f:
+ text = f.read()
+
+for t in tracers:
+    if t not in text:
+        print("ERROR: tracer \"%s\" is not mentioned in doc/environment_variables.md" % t)
+        errors += 1
+
+
+assert errors == 0
diff --git a/tools/run_tests/sanity/core_banned_functions.py b/tools/run_tests/sanity/core_banned_functions.py
index b394bbb..1f13905 100755
--- a/tools/run_tests/sanity/core_banned_functions.py
+++ b/tools/run_tests/sanity/core_banned_functions.py
@@ -41,6 +41,8 @@
     'grpc_closure_sched(' : ['src/core/lib/iomgr/closure.c'],
     'grpc_closure_run(' : ['src/core/lib/iomgr/closure.c'],
     'grpc_closure_list_sched(' : ['src/core/lib/iomgr/closure.c'],
+    'gpr_getenv_silent(' : ['src/core/lib/support/log.c', 'src/core/lib/support/env_linux.c', 
+                            'src/core/lib/support/env_posix.c', 'src/core/lib/support/env_windows.c'],
 }
 
 errors = 0
diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml
index 445f53e..a86ebee 100644
--- a/tools/run_tests/sanity/sanity_tests.yaml
+++ b/tools/run_tests/sanity/sanity_tests.yaml
@@ -1,8 +1,10 @@
 # a set of tests that are run in parallel for sanity tests
 - script: tools/run_tests/sanity/check_cache_mk.sh
+- script: tools/run_tests/sanity/check_owners.sh
 - script: tools/run_tests/sanity/check_sources_and_headers.py
 - script: tools/run_tests/sanity/check_submodules.sh
 - script: tools/run_tests/sanity/check_test_filtering.py
+- script: tools/run_tests/sanity/check_tracer_sanity.py
 - script: tools/run_tests/sanity/core_banned_functions.py
 - script: tools/buildgen/generate_projects.sh -j 3
   cpu_cost: 3
diff --git a/tools/ubsan_suppressions.txt b/tools/ubsan_suppressions.txt
index 83dcfc3..2dcfeea 100644
--- a/tools/ubsan_suppressions.txt
+++ b/tools/ubsan_suppressions.txt
@@ -7,3 +7,4 @@
 alignment:CRYPTO_gcm128_encrypt
 nonnull-attribute:google::protobuf::*
 alignment:google::protobuf::*
+nonnull-attribute:_tr_stored_block
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index b7696a9..5344d0a 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -118,6 +118,17 @@
 		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "byte_stream_test", "vcxproj\test\byte_stream_test\byte_stream_test.vcxproj", "{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_context_test", "vcxproj\test\census_context_test\census_context_test.vcxproj", "{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -731,7 +742,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
@@ -1166,6 +1176,30 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inproc_nosec_test", "vcxproj\test/end2end/fixtures\inproc_nosec_test\inproc_nosec_test.vcxproj", "{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{47C2CB41-4E9F-58B6-F606-F6FAED5D00ED} = {47C2CB41-4E9F-58B6-F606-F6FAED5D00ED}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inproc_test", "vcxproj\test/end2end/fixtures\inproc_test\inproc_test.vcxproj", "{59BB50B7-2E76-5EAA-781E-53228520635D}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{1F1F9084-2A93-B80E-364F-5754894AFAB4} = {1F1F9084-2A93-B80E-364F-5754894AFAB4}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "invalid_call_argument_test", "vcxproj\test\invalid_call_argument_test\invalid_call_argument_test.vcxproj", "{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1561,6 +1595,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stream_compression_test", "vcxproj\test\stream_compression_test\stream_compression_test.vcxproj", "{A5EE72A2-656C-0896-12F3-A92583CF7C61}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stream_owned_slice_test", "vcxproj\test\stream_owned_slice_test\stream_owned_slice_test.vcxproj", "{D5A20C05-D9B2-970B-8429-94BC3F58D1C4}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1905,6 +1950,22 @@
 		{D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Release-DLL|Win32.Build.0 = Release|Win32
 		{D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Release-DLL|x64.ActiveCfg = Release|x64
 		{D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Release-DLL|x64.Build.0 = Release|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug|x64.ActiveCfg = Debug|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release|Win32.ActiveCfg = Release|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release|x64.ActiveCfg = Release|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug|Win32.Build.0 = Debug|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug|x64.Build.0 = Debug|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release|Win32.Build.0 = Release|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release|x64.Build.0 = Release|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Debug-DLL|x64.Build.0 = Debug|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release-DLL|Win32.Build.0 = Release|Win32
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release-DLL|x64.ActiveCfg = Release|x64
+		{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}.Release-DLL|x64.Build.0 = Release|x64
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Debug|Win32.ActiveCfg = Debug|Win32
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Debug|x64.ActiveCfg = Debug|x64
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release|Win32.ActiveCfg = Release|Win32
@@ -3489,6 +3550,38 @@
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|Win32.Build.0 = Release|Win32
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.ActiveCfg = Release|x64
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.Build.0 = Release|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug|x64.ActiveCfg = Debug|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release|Win32.ActiveCfg = Release|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release|x64.ActiveCfg = Release|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug|Win32.Build.0 = Debug|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug|x64.Build.0 = Debug|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release|Win32.Build.0 = Release|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release|x64.Build.0 = Release|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Debug-DLL|x64.Build.0 = Debug|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release-DLL|Win32.Build.0 = Release|Win32
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release-DLL|x64.ActiveCfg = Release|x64
+		{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}.Release-DLL|x64.Build.0 = Release|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug|x64.ActiveCfg = Debug|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release|Win32.ActiveCfg = Release|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release|x64.ActiveCfg = Release|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug|Win32.Build.0 = Debug|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug|x64.Build.0 = Debug|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release|Win32.Build.0 = Release|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release|x64.Build.0 = Release|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Debug-DLL|x64.Build.0 = Debug|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release-DLL|Win32.Build.0 = Release|Win32
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release-DLL|x64.ActiveCfg = Release|x64
+		{59BB50B7-2E76-5EAA-781E-53228520635D}.Release-DLL|x64.Build.0 = Release|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|x64.ActiveCfg = Debug|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Release|Win32.ActiveCfg = Release|Win32
@@ -4065,6 +4158,22 @@
 		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|Win32.Build.0 = Release|Win32
 		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.ActiveCfg = Release|x64
 		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.Build.0 = Release|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|x64.ActiveCfg = Debug|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|Win32.ActiveCfg = Release|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|x64.ActiveCfg = Release|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|Win32.Build.0 = Debug|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|x64.Build.0 = Debug|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|Win32.Build.0 = Release|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|x64.Build.0 = Release|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|x64.Build.0 = Debug|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|Win32.Build.0 = Release|Win32
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|x64.ActiveCfg = Release|x64
+		{A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|x64.Build.0 = Release|x64
 		{D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Debug|x64.ActiveCfg = Debug|x64
 		{D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/grpc.sln b/vsprojects/grpc.sln
index d4a84fc..f400551 100644
--- a/vsprojects/grpc.sln
+++ b/vsprojects/grpc.sln
@@ -63,6 +63,7 @@
 	EndProjectSection
 	ProjectSection(ProjectDependencies) = postProject
 		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_error_details", "vcxproj\.\grpc++_error_details\grpc++_error_details.vcxproj", "{9F58AD72-49E1-4D10-B826-9E190AB0AAC0}"
@@ -80,7 +81,6 @@
 	ProjectSection(ProjectDependencies) = postProject
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_create_jwt", "vcxproj\.\grpc_create_jwt\grpc_create_jwt.vcxproj", "{77971F8D-F583-3E77-0E3C-6C1FB6B1749C}"
@@ -128,7 +128,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
 		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index 8599709..625c62a 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -303,6 +303,62 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\stub_options.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\avl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cmdline.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cpu.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\histogram.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\host_port.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\string_util.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\subprocess.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\thd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_gcc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_msvc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_pthread.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\useful.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
@@ -332,25 +388,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
   </ItemGroup>
@@ -366,6 +403,138 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_std.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\memory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\mpscq.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
@@ -454,12 +623,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\util\time_cc.cc">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
     </ClCompile>
   </ItemGroup>
@@ -467,6 +630,9 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
       <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
     </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index fd52731..ff9913a 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -124,15 +124,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\util\time_cc.cc">
       <Filter>src\cpp\util</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
       <Filter>src\cpp\codegen</Filter>
     </ClCompile>
@@ -273,6 +264,174 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\time.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\alloc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_atomic.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_sync.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\avl.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cmdline.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cpu.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\histogram.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\host_port.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\port_platform.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\string_util.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\subprocess.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_generic.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_posix.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\thd.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\time.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_gcc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_msvc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_pthread.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\useful.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -360,63 +519,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -458,6 +560,402 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h">
       <Filter>src\cpp\thread_manager</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h">
+      <Filter>src\core\lib\profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_atm.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_std.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\memory.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\mpscq.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_windows.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
+      <Filter>src\core\lib\debug</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
@@ -509,9 +1007,60 @@
     <Filter Include="include\grpc\impl\codegen">
       <UniqueIdentifier>{dc8bfccd-341f-26f0-8ee4-47dde62a6dd1}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc\support">
+      <UniqueIdentifier>{5ec10a44-9a09-9220-cf3b-b18ce6e4f70f}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{328ff211-2886-406e-56f9-18ba1686f363}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core">
+      <UniqueIdentifier>{d02f1155-7e7e-3736-3c69-dc9146dc523d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext">
+      <UniqueIdentifier>{96d09c4a-59f9-3486-6c2f-cbf695b285d8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{202b1172-189f-afc4-f16c-4ca12677b480}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\inproc">
+      <UniqueIdentifier>{635a93a8-e23a-a664-c9cb-0963736dd9ce}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{80567a8f-622f-a3ce-c12d-aebb63984b07}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\channel">
+      <UniqueIdentifier>{e769265c-8abd-cd64-2cc2-a52da484fe7b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\compression">
+      <UniqueIdentifier>{701b2d46-11c6-3640-b189-45287f00bee3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\debug">
+      <UniqueIdentifier>{ada68fd5-8e51-98cb-71a7-baf7989d8ffa}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\http">
+      <UniqueIdentifier>{e770844e-61d4-555e-59be-81288e21a35f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\iomgr">
+      <UniqueIdentifier>{04dfa1c8-7ffe-4f06-4a7c-37441dc75764}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\json">
+      <UniqueIdentifier>{a5d5bddf-6f19-b655-a03a-f30ff5c253a5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\profiling">
+      <UniqueIdentifier>{836e78ab-aaae-9dce-dd1e-06f03c436a13}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\slice">
+      <UniqueIdentifier>{afe126ba-52c9-1daa-d174-8ee8aade08c2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\support">
+      <UniqueIdentifier>{83b45914-6f97-b4ad-f2d0-cc56a10ea1bb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\surface">
+      <UniqueIdentifier>{fb2276d7-5a11-f1d9-82c3-e7c7f1155523}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\transport">
+      <UniqueIdentifier>{4bd7971a-68f7-0d5a-f502-6dea3099caaa}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\cpp">
       <UniqueIdentifier>{2420a905-e4f1-a5aa-a364-6a112878a39e}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj
new file mode 100644
index 0000000..5a84ab4
--- /dev/null
+++ b/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{1D4003D7-5BF1-9FE6-BAF7-23B174D942AC}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>grpc++_test_util_unsecure</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>grpc++_test_util_unsecure</TargetName>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\byte_buffer_proto_helper.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\subprocess.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\duplicate\echo_duplicate.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\duplicate\echo_duplicate.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\duplicate\echo_duplicate.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\duplicate\echo_duplicate.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\byte_buffer_proto_helper.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\subprocess.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj.filters
new file mode 100644
index 0000000..b39f96f
--- /dev/null
+++ b/vsprojects/vcxproj/grpc++_test_util_unsecure/grpc++_test_util_unsecure.vcxproj.filters
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.proto">
+      <Filter>src\proto\grpc\health\v1</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\duplicate\echo_duplicate.proto">
+      <Filter>src\proto\grpc\testing\duplicate</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.cc">
+      <Filter>test\cpp\end2end</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\byte_buffer_proto_helper.cc">
+      <Filter>test\cpp\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
+      <Filter>test\cpp\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\subprocess.cc">
+      <Filter>test\cpp\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
+      <Filter>src\cpp\codegen</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
+      <Filter>include\grpc++\impl\codegen\security</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h">
+      <Filter>test\cpp\end2end</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\byte_buffer_proto_helper.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\subprocess.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="include">
+      <UniqueIdentifier>{781a1608-4ec4-84b1-fd7e-e57adad0005d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{da1ebc2d-b558-bdc0-9541-c9f819d11c04}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++">
+      <UniqueIdentifier>{a39a48c0-c9a5-3604-e938-802c36d53216}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl">
+      <UniqueIdentifier>{1fdb8853-a861-f8e3-fa1c-0543fa78879f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen">
+      <UniqueIdentifier>{2546f4ae-8381-e6a9-ddac-41d12c404b5f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen\security">
+      <UniqueIdentifier>{f3b5631d-4a82-0785-9358-cf5062293391}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{19f6c9d1-1185-a5de-881e-5224d1058d5e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{967583b5-ee23-687f-2474-520655e0be4a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src">
+      <UniqueIdentifier>{391a84b9-78a5-9954-e923-f8d055b3481b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp">
+      <UniqueIdentifier>{4062f6b9-f1ff-68e8-72bc-30277514b0ee}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\cpp\codegen">
+      <UniqueIdentifier>{8a7e7d59-50b8-04bf-e9c7-67ebf0021873}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{1b71252d-1742-e9be-64f9-562af348bafd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{ce9a06e6-fe2f-f9fa-03ae-0e39e730c312}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\health">
+      <UniqueIdentifier>{471fdb3b-4dc0-4a35-3667-22e9f857db8e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\health\v1">
+      <UniqueIdentifier>{7e63feec-8f56-cd35-b7d6-73db98dbdde2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing">
+      <UniqueIdentifier>{4ffb2a33-1a46-184c-555e-be927e3747fd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing\duplicate">
+      <UniqueIdentifier>{2bc8042f-43c5-737c-4d52-553402259478}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{9d840e55-92ac-10af-2ac1-9c0af3b05a5c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{2668f96a-1d73-d007-92ff-9b50e2fba1b0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\end2end">
+      <UniqueIdentifier>{63c12fd2-9e66-f7b8-1eec-951e7d48e343}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\util">
+      <UniqueIdentifier>{e08c5a81-5645-f71c-59ab-98d2f3e41417}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 30e4cf7..baeb6e3 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -303,6 +303,62 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\stub_options.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\alloc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\avl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cmdline.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cpu.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\histogram.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\host_port.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\string_util.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\subprocess.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\thd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_gcc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_msvc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_pthread.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\useful.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
@@ -332,25 +388,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
@@ -360,6 +397,138 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_std.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\memory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\mpscq.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
@@ -438,12 +607,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\util\time_cc.cc">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
     </ClCompile>
   </ItemGroup>
@@ -454,9 +617,6 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
       <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 3d2c74a..5820ce0 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -109,15 +109,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\util\time_cc.cc">
       <Filter>src\cpp\util</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
-      <Filter>third_party\nanopb</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\codegen\codegen_init.cc">
       <Filter>src\cpp\codegen</Filter>
     </ClCompile>
@@ -258,6 +249,174 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\support\time.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\alloc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_atomic.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_gcc_sync.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\atm_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\avl.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cmdline.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\cpu.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\histogram.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\host_port.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\log_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\port_platform.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\string_util.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\subprocess.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_generic.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_posix.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\sync_windows.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\thd.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\time.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_gcc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_msvc.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\tls_pthread.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\useful.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -345,63 +504,6 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
-      <Filter>include\grpc\impl\codegen</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h">
@@ -425,6 +527,402 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h">
       <Filter>src\cpp\thread_manager</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h">
+      <Filter>src\core\lib\profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_atm.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\atomic_with_std.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\memory.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\mpscq.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_windows.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\thd_internal.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\time_precise.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\tmpfile.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h">
+      <Filter>src\core\lib\channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
+      <Filter>src\core\lib\http</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
+      <Filter>src\core\lib\json</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
+      <Filter>src\core\lib\debug</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
@@ -476,9 +974,60 @@
     <Filter Include="include\grpc\impl\codegen">
       <UniqueIdentifier>{adf6b8e3-4a4b-cb35-bb3d-568af97b58d1}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc\support">
+      <UniqueIdentifier>{9d6d36f2-26e7-a66b-c19d-a958b80878d6}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{cce6a85d-1111-3834-6825-31e170d93cff}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core">
+      <UniqueIdentifier>{595f2ea0-aafb-87e5-c938-db3ff0b0c69a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext">
+      <UniqueIdentifier>{52eca76b-9502-3d96-9064-6415226a860f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{8e70201f-3b54-d3cb-8b30-ebe0d96a9b2a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\inproc">
+      <UniqueIdentifier>{ecf09c42-c470-1883-35d7-442453ea8370}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{cf8fd5d8-ff54-331d-2d20-36d6cae0e14b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\channel">
+      <UniqueIdentifier>{7e0225af-000b-4873-1c16-caffffbfd084}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\compression">
+      <UniqueIdentifier>{0bbdbf56-83ad-bb4b-c4e2-a6d38c342179}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\debug">
+      <UniqueIdentifier>{3875f7d7-ff11-c91d-0f98-810260cb554b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\http">
+      <UniqueIdentifier>{4bd405b9-af65-f0a6-d67a-433f75900668}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\iomgr">
+      <UniqueIdentifier>{f4b146e4-8fba-83a6-1cc1-1262ebb785e8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\json">
+      <UniqueIdentifier>{b83c8e70-e491-f6f9-a08c-85f632bb61d2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\profiling">
+      <UniqueIdentifier>{c3b582f8-079a-5936-7694-54cd75a7e61e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\slice">
+      <UniqueIdentifier>{0d6d88e2-8549-5118-8b78-06e8283dadcb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\support">
+      <UniqueIdentifier>{a5139298-498a-41d4-59fd-c38d8f0380c1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\surface">
+      <UniqueIdentifier>{1d59dcef-3358-d0ab-fa42-64da74065785}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\transport">
+      <UniqueIdentifier>{ba865739-5dd9-6731-6772-48c25d45134f}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\cpp">
       <UniqueIdentifier>{1e5fd68c-bd87-e803-42b0-75a7fa19b91d}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index f9badbb..3f711f6 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -267,17 +267,6 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
@@ -298,9 +287,91 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\gts_transport_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_adapter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
@@ -311,6 +382,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
@@ -333,9 +405,11 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
@@ -411,85 +485,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_adapter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_ev_driver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_wrapper.h" />
@@ -539,6 +540,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
@@ -781,6 +784,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
@@ -875,6 +880,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\gts_transport_security.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\tsi\transport_security.c">
@@ -937,6 +944,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index f3e997e..662eddf 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -31,6 +31,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
       <Filter>src\core\lib\compression</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
       <Filter>src\core\lib\http</Filter>
     </ClCompile>
@@ -394,6 +397,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
@@ -535,6 +541,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.c">
       <Filter>src\core\tsi</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\tsi\gts_transport_security.c">
+      <Filter>src\core\tsi</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.c">
       <Filter>src\core\tsi</Filter>
     </ClCompile>
@@ -628,6 +637,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
       <Filter>src\core\ext\transport\chttp2\client\insecure</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_plugin.c">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.c">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
       <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
     </ClCompile>
@@ -750,39 +765,6 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
-      <Filter>include\grpc\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
@@ -843,11 +825,257 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
+      <Filter>src\core\ext\filters\http\client</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
+      <Filter>src\core\ext\filters\http\server</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h">
+      <Filter>src\core\lib\security\context</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h">
+      <Filter>src\core\lib\security\credentials\composite</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h">
+      <Filter>src\core\lib\security\credentials</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h">
+      <Filter>src\core\lib\security\credentials\fake</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h">
+      <Filter>src\core\lib\security\credentials\google_default</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h">
+      <Filter>src\core\lib\security\credentials\iam</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h">
+      <Filter>src\core\lib\security\credentials\oauth2</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h">
+      <Filter>src\core\lib\security\credentials\plugin</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h">
+      <Filter>src\core\lib\security\credentials\ssl</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\gts_transport_security.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_adapter.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h">
+      <Filter>src\core\tsi</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h">
+      <Filter>src\core\ext\transport\chttp2\server</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
+      <Filter>src\core\ext\filters\deadline</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h">
+      <Filter>src\core\ext\transport\chttp2\client</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
@@ -878,6 +1106,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
       <Filter>src\core\lib\compression</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
       <Filter>src\core\lib\http</Filter>
     </ClInclude>
@@ -944,6 +1175,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -953,6 +1187,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -1178,213 +1415,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
       <Filter>src\core\lib\debug</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
-      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
-      <Filter>src\core\ext\filters\http\client</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
-      <Filter>src\core\ext\filters\http\message_compress</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
-      <Filter>src\core\ext\filters\http\server</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h">
-      <Filter>src\core\lib\security\context</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h">
-      <Filter>src\core\lib\security\credentials\composite</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h">
-      <Filter>src\core\lib\security\credentials</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h">
-      <Filter>src\core\lib\security\credentials\fake</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h">
-      <Filter>src\core\lib\security\credentials\google_default</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h">
-      <Filter>src\core\lib\security\credentials\iam</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h">
-      <Filter>src\core\lib\security\credentials\jwt</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h">
-      <Filter>src\core\lib\security\credentials\jwt</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h">
-      <Filter>src\core\lib\security\credentials\jwt</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h">
-      <Filter>src\core\lib\security\credentials\oauth2</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h">
-      <Filter>src\core\lib\security\credentials\plugin</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h">
-      <Filter>src\core\lib\security\credentials\ssl</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h">
-      <Filter>src\core\lib\security\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h">
-      <Filter>src\core\lib\security\util</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\fake_transport_security.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_transport_security.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\ssl_types.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_adapter.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\tsi\transport_security_interface.h">
-      <Filter>src\core\tsi</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h">
-      <Filter>src\core\ext\transport\chttp2\server</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
-      <Filter>src\core\ext\filters\deadline</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h">
-      <Filter>src\core\ext\transport\chttp2\client</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h">
       <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
     </ClInclude>
@@ -1403,18 +1433,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h">
       <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.h">
       <Filter>src\core\ext\filters\client_channel\resolver\fake</Filter>
     </ClInclude>
@@ -1634,6 +1652,9 @@
     <Filter Include="src\core\ext\transport\chttp2\transport">
       <UniqueIdentifier>{6f34254e-e69f-c9b4-156d-5024bade5408}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\ext\transport\inproc">
+      <UniqueIdentifier>{fb9e878e-fc50-40af-7646-074229a9d676}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib">
       <UniqueIdentifier>{5b2ded3f-84a5-f6b4-2060-286c7d1dc945}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 1899be9..fa31dbe 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -147,17 +147,6 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
@@ -196,116 +185,48 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\client_certs.c">
@@ -366,6 +287,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
@@ -598,6 +521,102 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\channel_connectivity.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\http_filters_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 9c81fc5..fc9f64a 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -88,6 +88,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
       <Filter>src\core\lib\compression</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
       <Filter>src\core\lib\http</Filter>
     </ClCompile>
@@ -436,41 +439,152 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
       <Filter>src\core\lib\debug</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\channel_connectivity.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_plugin.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
+      <Filter>src\core\ext\filters\deadline</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.c">
+      <Filter>src\core\ext\filters\http\client</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\http_filters_plugin.c">
+      <Filter>src\core\ext\filters\http</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.c">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.c">
+      <Filter>src\core\ext\filters\http\server</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
-      <Filter>include\grpc\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
@@ -581,335 +695,131 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h">
-      <Filter>src\core\lib\channel</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
-      <Filter>src\core\lib\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
-      <Filter>src\core\lib\compression</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
-      <Filter>src\core\lib\http</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
-      <Filter>src\core\lib\http</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
-      <Filter>src\core\lib\http</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
+      <Filter>src\core\ext\filters\deadline</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
+      <Filter>src\core\ext\filters\http\client</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.h">
-      <Filter>src\core\lib\iomgr</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\port.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
-      <Filter>src\core\lib\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
-      <Filter>src\core\lib\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
-      <Filter>src\core\lib\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
-      <Filter>src\core\lib\json</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\b64.h">
-      <Filter>src\core\lib\slice</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
-      <Filter>src\core\lib\slice</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
-      <Filter>src\core\lib\slice</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
-      <Filter>src\core\lib\slice</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
-      <Filter>src\core\lib\slice</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
-      <Filter>src\core\lib\surface</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
-      <Filter>src\core\lib\debug</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
+      <Filter>src\core\ext\filters\http\server</Filter>
     </ClInclude>
   </ItemGroup>
 
@@ -926,9 +836,6 @@
     <Filter Include="include\grpc\impl\codegen">
       <UniqueIdentifier>{8e97f1e1-f4d1-a56e-0837-7901778fb3b9}</UniqueIdentifier>
     </Filter>
-    <Filter Include="include\grpc\support">
-      <UniqueIdentifier>{b783a829-3703-129f-39ee-528ac0a06e06}</UniqueIdentifier>
-    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{7d107d7c-1da3-9525-3ba1-3a411b552ea8}</UniqueIdentifier>
     </Filter>
@@ -950,6 +857,33 @@
     <Filter Include="src\core\ext\filters\client_channel\resolver\fake">
       <UniqueIdentifier>{9e94ffec-fe00-d132-db50-c4a3c218f102}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\ext\filters\deadline">
+      <UniqueIdentifier>{2c9ab189-bb7e-355d-9f37-385472e86b9f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http">
+      <UniqueIdentifier>{4503bfa6-92be-99d8-8c6b-feeb42bbdd1c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\client">
+      <UniqueIdentifier>{6d9ffdbe-4d2f-b0c4-8abe-a548ffde6ad6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\message_compress">
+      <UniqueIdentifier>{a6c2fe73-3b25-084c-68d7-9673ec7b872a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\server">
+      <UniqueIdentifier>{ec11748c-79ef-f224-2072-e3006d8638f4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{b5f17b17-8012-87c9-dfb2-428dd29d0b94}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2">
+      <UniqueIdentifier>{608f56aa-d257-f25b-14aa-1776a771defd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\alpn">
+      <UniqueIdentifier>{49d381db-172f-9765-4135-d7a10c4485bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\transport">
+      <UniqueIdentifier>{4395ba2e-6b6d-ea05-8a1e-915b8f0f85f6}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib">
       <UniqueIdentifier>{f4e8c61e-1ca6-0fdd-7b5e-b7f9a30c9a21}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
index d9977f7..457dbd5 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
@@ -147,6 +147,27 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+  </ItemGroup>
+  <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\cq_verifier.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\http_proxy_fixture.h" />
@@ -162,6 +183,48 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.c">
@@ -194,6 +257,354 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_common.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_ifaddrs.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_noifaddrs.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\b64.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\channel_connectivity.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\http_filters_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
@@ -205,9 +616,6 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
       <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
index 0a0590e..49e886d 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
@@ -46,6 +46,587 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_factory.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.c">
+      <Filter>src\core\lib\channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
+      <Filter>src\core\lib\http</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
+      <Filter>src\core\lib\http</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
+      <Filter>src\core\lib\http</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\combiner.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resource_quota.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_factory_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_mutator.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_common.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_ifaddrs.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_utils_posix_noifaddrs.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_cv.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
+      <Filter>src\core\lib\json</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
+      <Filter>src\core\lib\json</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
+      <Filter>src\core\lib\json</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
+      <Filter>src\core\lib\json</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\b64.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.cc">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
+      <Filter>src\core\lib\debug</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\channel_connectivity.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_plugin.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.c">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
+      <Filter>src\core\ext\filters\deadline</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_plugin.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\writing.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.c">
+      <Filter>src\core\ext\filters\http\client</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\http_filters_plugin.c">
+      <Filter>src\core\ext\filters\http</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.c">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.c">
+      <Filter>src\core\ext\filters\http\server</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.h">
@@ -93,9 +674,147 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
+      <Filter>src\core\ext\filters\deadline</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
+      <Filter>src\core\ext\filters\http\client</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
+      <Filter>src\core\ext\filters\http\server</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
+    <Filter Include="include">
+      <UniqueIdentifier>{9793fab6-15ae-1f61-712d-c3d673654d72}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{c2447106-a6bf-6b88-9ad0-a42b7ac1573c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{dba70812-267b-656c-9f8c-636338d3f5c0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{b9e2ddac-f042-3042-ba4b-79ba4445e68c}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src">
       <UniqueIdentifier>{65483377-42fd-137e-3847-00dfd4675db3}</UniqueIdentifier>
     </Filter>
@@ -117,6 +836,63 @@
     <Filter Include="src\core\ext\filters\client_channel\resolver\fake">
       <UniqueIdentifier>{2d280bd0-f4ee-d1f2-4d70-174147ac0dbc}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\ext\filters\deadline">
+      <UniqueIdentifier>{6820a68f-2aa3-8b45-ddea-294656d531f6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http">
+      <UniqueIdentifier>{b7df4d88-fa6b-6bd3-579e-b5f086ba6299}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\client">
+      <UniqueIdentifier>{37d93a32-6a75-3b9e-35a4-c47f0a2d274a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\message_compress">
+      <UniqueIdentifier>{a4bd6a23-c8e1-4e35-f9eb-6434a86f38f0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\filters\http\server">
+      <UniqueIdentifier>{2dd536f5-341a-771f-4853-a95522e59224}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport">
+      <UniqueIdentifier>{fb32254e-a807-768a-3686-4e87f3bf1e8e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2">
+      <UniqueIdentifier>{87c61e56-5090-5e1a-22af-02e3c8bf4a2a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\alpn">
+      <UniqueIdentifier>{e50ce1d1-6b17-dad2-9ef3-46f68d4bee1b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\ext\transport\chttp2\transport">
+      <UniqueIdentifier>{67007111-23fe-296f-1808-91f2b96a31aa}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib">
+      <UniqueIdentifier>{e3d002a7-9318-1ac5-4259-e177f58ccc9a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\channel">
+      <UniqueIdentifier>{ac14fd16-a4af-6b22-4226-2d7dabf25409}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\compression">
+      <UniqueIdentifier>{24268e45-f6c3-6024-b49a-d01bb9c12d96}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\debug">
+      <UniqueIdentifier>{0be401bd-3e26-dead-fdf4-2ce27a1ac3a3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\http">
+      <UniqueIdentifier>{ac2f12e3-ac77-f0a7-d15d-92899e61ed25}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\iomgr">
+      <UniqueIdentifier>{9015222c-df04-298f-3f2c-d19babffc180}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\json">
+      <UniqueIdentifier>{c3ff117a-aae9-dedd-2f5a-888f0383cbb8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\slice">
+      <UniqueIdentifier>{588ffbfc-2f94-a99f-85b0-4c47ec9f8d13}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\surface">
+      <UniqueIdentifier>{732318c6-bb34-9a99-611b-9928db3d4e2a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\transport">
+      <UniqueIdentifier>{2c0ca4a1-38df-329d-eeba-5c5b61dc81a5}</UniqueIdentifier>
+    </Filter>
     <Filter Include="test">
       <UniqueIdentifier>{037c7645-1698-cf2d-4163-525240323101}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 3a865f3..c0ce8f0 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -258,17 +258,6 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
@@ -288,9 +277,65 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
@@ -301,6 +346,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
@@ -323,9 +369,11 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
@@ -401,50 +449,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_ev_driver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_wrapper.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\fake\fake_resolver.h" />
@@ -456,10 +460,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\base_resources.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
@@ -506,6 +506,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
@@ -750,6 +752,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.c">
@@ -844,6 +848,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_plugin.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\dns_resolver_ares.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_ev_driver_posix.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 0310ebc..2d2a820 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -34,6 +34,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
       <Filter>src\core\lib\compression</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.c">
+      <Filter>src\core\lib\compression</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
       <Filter>src\core\lib\http</Filter>
     </ClCompile>
@@ -400,6 +403,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\flow_control.c">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
@@ -541,6 +547,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.c">
       <Filter>src\core\ext\filters\deadline</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_plugin.c">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.c">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\dns_resolver_ares.c">
       <Filter>src\core\ext\filters\client_channel\resolver\dns\c_ares</Filter>
     </ClCompile>
@@ -663,39 +675,6 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
-      <Filter>include\grpc</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
-      <Filter>include\grpc\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
@@ -753,11 +732,179 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\support\workaround_list.h">
+      <Filter>include\grpc\support</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\census.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
+      <Filter>src\core\ext\transport\chttp2\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
+      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
+      <Filter>src\core\ext\filters\http\client</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
+      <Filter>src\core\ext\filters\http\message_compress</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
+      <Filter>src\core\ext\filters\http\server</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h">
+      <Filter>src\core\ext\transport\chttp2\server</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h">
+      <Filter>src\core\ext\transport\chttp2\client</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
+      <Filter>src\core\ext\filters\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
+      <Filter>src\core\ext\filters\deadline</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\inproc\inproc_transport.h">
+      <Filter>src\core\ext\transport\inproc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
@@ -788,6 +935,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
       <Filter>src\core\lib\compression</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\stream_compression.h">
+      <Filter>src\core\lib\compression</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
       <Filter>src\core\lib\http</Filter>
     </ClInclude>
@@ -854,6 +1004,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_uv.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -863,6 +1016,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\nameser.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -1088,138 +1244,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
       <Filter>src\core\lib\debug</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_data.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_goaway.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_ping.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_rst_stream.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_settings.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\frame_window_update.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_settings.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
-      <Filter>src\core\ext\transport\chttp2\alpn</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\client\http_client_filter.h">
-      <Filter>src\core\ext\filters\http\client</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\message_compress\message_compress_filter.h">
-      <Filter>src\core\ext\filters\http\message_compress</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\http\server\http_server_filter.h">
-      <Filter>src\core\ext\filters\http\server</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h">
-      <Filter>src\core\ext\transport\chttp2\server</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h">
-      <Filter>src\core\ext\transport\chttp2\client</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\client_channel_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\connector.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_connect_handshaker.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\http_proxy.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\parse_address.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\proxy_mapper_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_factory.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver_registry.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\retry_throttle.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\subchannel_index.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h">
-      <Filter>src\core\ext\filters\client_channel</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h">
-      <Filter>src\core\ext\filters\deadline</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_ev_driver.h">
       <Filter>src\core\ext\filters\client_channel\resolver\dns\c_ares</Filter>
     </ClInclude>
@@ -1253,18 +1277,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h">
       <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
-      <Filter>third_party\nanopb</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
@@ -1463,6 +1475,9 @@
     <Filter Include="src\core\ext\transport\chttp2\transport">
       <UniqueIdentifier>{45b20f28-376c-9dea-1800-8a0193411946}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\ext\transport\inproc">
+      <UniqueIdentifier>{287a62fa-b646-5062-49c4-9e7bd5bc5b96}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib">
       <UniqueIdentifier>{8bd5b461-bff8-6aa8-b5a6-85da2834eb8a}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/test/alarm_cpp_test/alarm_cpp_test.vcxproj b/vsprojects/vcxproj/test/alarm_cpp_test/alarm_cpp_test.vcxproj
index 10541cb..0caf8b6 100644
--- a/vsprojects/vcxproj/test/alarm_cpp_test/alarm_cpp_test.vcxproj
+++ b/vsprojects/vcxproj/test/alarm_cpp_test/alarm_cpp_test.vcxproj
@@ -164,17 +164,17 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
-      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util_unsecure\grpc++_test_util_unsecure.vcxproj">
+      <Project>{1D4003D7-5BF1-9FE6-BAF7-23B174D942AC}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
       <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
diff --git a/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj b/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj
new file mode 100644
index 0000000..5d65647
--- /dev/null
+++ b/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9AEDA345-E3E8-BFE9-11BF-64949EF41C9C}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>byte_stream_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>byte_stream_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\byte_stream_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj.filters b/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj.filters
new file mode 100644
index 0000000..65e35b7
--- /dev/null
+++ b/vsprojects/vcxproj/test/byte_stream_test/byte_stream_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\byte_stream_test.c">
+      <Filter>test\core\transport</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{f172d292-4ad6-342a-f27a-096c06d43a31}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{d7f690de-dfe0-56fc-ff3b-38eec3931699}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\transport">
+      <UniqueIdentifier>{f78f56ef-47df-c99d-18f0-86277f7013f3}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj b/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj
new file mode 100644
index 0000000..7850867
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{D0D0CAE5-3D8C-390E-0F2F-58312AEADC32}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>inproc_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>inproc_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\inproc.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_nosec_tests\end2end_nosec_tests.vcxproj">
+      <Project>{47C2CB41-4E9F-58B6-F606-F6FAED5D00ED}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj.filters
new file mode 100644
index 0000000..25ffa17
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/inproc_nosec_test/inproc_nosec_test.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\inproc.c">
+      <Filter>test\core\end2end\fixtures</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{ed71b5b3-f12c-a50c-1848-91bc295dc7a6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{89470314-c22a-c997-e533-5d1e04174120}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end">
+      <UniqueIdentifier>{eb7f58b2-73e3-5556-41ca-b301f39a61eb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end\fixtures">
+      <UniqueIdentifier>{c6974b84-e7ab-3022-7a93-cb206fd189bc}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj b/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj
new file mode 100644
index 0000000..7d6d143
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{59BB50B7-2E76-5EAA-781E-53228520635D}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>inproc_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>inproc_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\inproc.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_tests\end2end_tests.vcxproj">
+      <Project>{1F1F9084-2A93-B80E-364F-5754894AFAB4}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj.filters b/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj.filters
new file mode 100644
index 0000000..6db8387
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end/fixtures/inproc_test/inproc_test.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\inproc.c">
+      <Filter>test\core\end2end\fixtures</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{18db9e76-ea71-0740-617f-ab04f151392c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{8c1ba9f9-2af8-e515-d621-ff46b37b4838}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end">
+      <UniqueIdentifier>{16f70dc0-364b-4d2b-edf6-dfa731c168d7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end\fixtures">
+      <UniqueIdentifier>{854c88c3-4f3d-7ef0-6a08-d4f84a0ff92e}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
index 4d02c88..249d99b 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
@@ -231,6 +231,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\proxy_auth.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\request_with_flags.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
index 89316bc..3a2105e 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
@@ -121,6 +121,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\proxy_auth.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
index 9573111..b7a2ecd 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
@@ -233,6 +233,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\proxy_auth.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\request_with_flags.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
index 7d02fc3..1626b77 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
@@ -124,6 +124,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\proxy_auth.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/grpc_benchmark/grpc_benchmark.vcxproj b/vsprojects/vcxproj/test/grpc_benchmark/grpc_benchmark.vcxproj
index 58586f0..a86f83c 100644
--- a/vsprojects/vcxproj/test/grpc_benchmark/grpc_benchmark.vcxproj
+++ b/vsprojects/vcxproj/test/grpc_benchmark/grpc_benchmark.vcxproj
@@ -172,14 +172,14 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\benchmark\benchmark.vcxproj">
       <Project>{07978586-E47C-8709-A63E-895FBF3C3C7D}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/server_builder_test/server_builder_test.vcxproj b/vsprojects/vcxproj/test/server_builder_test/server_builder_test.vcxproj
index ebbfd59..1b140dc 100644
--- a/vsprojects/vcxproj/test/server_builder_test/server_builder_test.vcxproj
+++ b/vsprojects/vcxproj/test/server_builder_test/server_builder_test.vcxproj
@@ -180,20 +180,20 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
-      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util_unsecure\grpc++_test_util_unsecure.vcxproj">
+      <Project>{1D4003D7-5BF1-9FE6-BAF7-23B174D942AC}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
       <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
       <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
diff --git a/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj b/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj
new file mode 100644
index 0000000..58af3b4
--- /dev/null
+++ b/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{F33164EE-1406-7E49-E894-7E795146B882}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>server_request_call_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>server_request_call_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\server\server_request_call_test.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util_unsecure\grpc++_test_util_unsecure.vcxproj">
+      <Project>{1D4003D7-5BF1-9FE6-BAF7-23B174D942AC}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj.filters b/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj.filters
new file mode 100644
index 0000000..a82cfb1
--- /dev/null
+++ b/vsprojects/vcxproj/test/server_request_call_test/server_request_call_test.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\server\server_request_call_test.cc">
+      <Filter>test\cpp\server</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="src">
+      <UniqueIdentifier>{48583c1d-014b-ecf7-ece7-98145537c913}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{f931e5e2-7d0e-a8d9-b072-1ed8095387a3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{55f7d797-a139-d9c5-8cc3-7fde09c1d28b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing">
+      <UniqueIdentifier>{1b39e313-5219-fbc1-9d88-9154b406e4ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{613e68e0-6bd4-3936-f8c2-34e255688225}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{871d6909-5ab9-336d-41ea-380563fcd3b3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\server">
+      <UniqueIdentifier>{4939f87e-df84-7c23-cd10-c23c06c72683}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj
new file mode 100644
index 0000000..7faf665
--- /dev/null
+++ b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{A5EE72A2-656C-0896-12F3-A92583CF7C61}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>stream_compression_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>stream_compression_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\compression\stream_compression_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters
new file mode 100644
index 0000000..a636282
--- /dev/null
+++ b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\compression\stream_compression_test.c">
+      <Filter>test\core\compression</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{22ec1dc6-29e1-32ac-1494-43bb7f211422}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{62cac7ff-76a5-35ff-1e73-a8508e826ba3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\compression">
+      <UniqueIdentifier>{02c8e4fc-eeda-2f58-227f-ebef22a39562}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/thread_manager_test/thread_manager_test.vcxproj b/vsprojects/vcxproj/test/thread_manager_test/thread_manager_test.vcxproj
index 2c35a03..bfc9977 100644
--- a/vsprojects/vcxproj/test/thread_manager_test/thread_manager_test.vcxproj
+++ b/vsprojects/vcxproj/test/thread_manager_test/thread_manager_test.vcxproj
@@ -164,11 +164,11 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
       <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
diff --git a/vsprojects/vcxproj/test/thread_stress_test/thread_stress_test.vcxproj b/vsprojects/vcxproj/test/thread_stress_test/thread_stress_test.vcxproj
index 44b0a35..a62a0db 100644
--- a/vsprojects/vcxproj/test/thread_stress_test/thread_stress_test.vcxproj
+++ b/vsprojects/vcxproj/test/thread_stress_test/thread_stress_test.vcxproj
@@ -164,17 +164,17 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
-      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util_unsecure\grpc++_test_util_unsecure.vcxproj">
+      <Project>{1D4003D7-5BF1-9FE6-BAF7-23B174D942AC}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj">
+      <Project>{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
       <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>