diff --git a/BUILD b/BUILD
index 02b4fc62edb9c2b2c3c366b6f6dacb2d3c36f3ba..b2750c8dd194d1e376f9226f6f41876202d19995 100644
--- a/BUILD
+++ b/BUILD
@@ -422,6 +422,8 @@ grpc_cc_library(
         "src/core/lib/channel/connected_channel.c",
         "src/core/lib/channel/deadline_filter.c",
         "src/core/lib/channel/handshaker.c",
+        "src/core/lib/channel/handshaker_factory.c",
+        "src/core/lib/channel/handshaker_registry.c",
         "src/core/lib/channel/http_client_filter.c",
         "src/core/lib/channel/http_server_filter.c",
         "src/core/lib/channel/message_size_filter.c",
@@ -537,6 +539,8 @@ grpc_cc_library(
         "src/core/lib/channel/context.h",
         "src/core/lib/channel/deadline_filter.h",
         "src/core/lib/channel/handshaker.h",
+        "src/core/lib/channel/handshaker_factory.h",
+        "src/core/lib/channel/handshaker_registry.h",
         "src/core/lib/channel/http_client_filter.h",
         "src/core/lib/channel/http_server_filter.h",
         "src/core/lib/channel/message_size_filter.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 220a8dd3414d3dfd5244ab63fb8bb4225518f756..9d67736c13b679e57d8ec1266fe893df2267dc32 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,7 +66,13 @@ set_property(CACHE gRPC_PROTOBUF_PROVIDER PROPERTY STRINGS "module" "package")
 set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library")
 
 if (MSVC)
-  add_definitions( -D_WIN32_WINNT=0x600 )
+  add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
+  # needed to compile boringssl
+  add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027)
+  # needed to compile protobuf
+  add_definitions(/wd4065 /wd4506)
+  # TODO(jtattermusch): revisit C4267 occurrences throughout the code
+  add_definitions(/wd4267)
 endif()
 
 if (gRPC_USE_PROTO_LITE)
@@ -293,6 +299,8 @@ add_library(grpc
   src/core/lib/channel/connected_channel.c
   src/core/lib/channel/deadline_filter.c
   src/core/lib/channel/handshaker.c
+  src/core/lib/channel/handshaker_factory.c
+  src/core/lib/channel/handshaker_registry.c
   src/core/lib/channel/http_client_filter.c
   src/core/lib/channel/http_server_filter.c
   src/core/lib/channel/message_size_filter.c
@@ -576,6 +584,8 @@ add_library(grpc_cronet
   src/core/lib/channel/connected_channel.c
   src/core/lib/channel/deadline_filter.c
   src/core/lib/channel/handshaker.c
+  src/core/lib/channel/handshaker_factory.c
+  src/core/lib/channel/handshaker_registry.c
   src/core/lib/channel/http_client_filter.c
   src/core/lib/channel/http_server_filter.c
   src/core/lib/channel/message_size_filter.c
@@ -830,6 +840,8 @@ add_library(grpc_unsecure
   src/core/lib/channel/connected_channel.c
   src/core/lib/channel/deadline_filter.c
   src/core/lib/channel/handshaker.c
+  src/core/lib/channel/handshaker_factory.c
+  src/core/lib/channel/handshaker_registry.c
   src/core/lib/channel/http_client_filter.c
   src/core/lib/channel/http_server_filter.c
   src/core/lib/channel/message_size_filter.c
@@ -1301,6 +1313,8 @@ add_library(grpc++_cronet
   src/core/lib/channel/connected_channel.c
   src/core/lib/channel/deadline_filter.c
   src/core/lib/channel/handshaker.c
+  src/core/lib/channel/handshaker_factory.c
+  src/core/lib/channel/handshaker_registry.c
   src/core/lib/channel/http_client_filter.c
   src/core/lib/channel/http_server_filter.c
   src/core/lib/channel/message_size_filter.c
@@ -1581,45 +1595,6 @@ if (gRPC_INSTALL)
 endif()
 
   
-add_library(grpc++_reflection
-  src/cpp/ext/proto_server_reflection.cc
-  src/cpp/ext/proto_server_reflection_plugin.cc
-  src/proto/grpc/reflection/v1alpha/reflection.proto
-)
-
-target_include_directories(grpc++_reflection
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-)
-
-target_link_libraries(grpc++_reflection
-  grpc++
-)
-
-foreach(_hdr
-  include/grpc++/ext/proto_server_reflection_plugin.h
-)
-  string(REPLACE "include/" "" _path ${_hdr})
-  get_filename_component(_path ${_path} PATH)
-  install(FILES ${_hdr}
-    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}"
-  )
-endforeach()
-
-  
-if (gRPC_INSTALL)
-  install(TARGETS grpc++_reflection EXPORT gRPCTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  )
-endif()
-
-  
 add_library(grpc++_unsecure
   src/cpp/client/insecure_credentials.cc
   src/cpp/common/insecure_create_auth_context.cc
@@ -1821,35 +1796,6 @@ if (gRPC_INSTALL)
   )
 endif()
 
-  
-add_library(grpc_csharp_ext
-  src/csharp/ext/grpc_csharp_ext.c
-)
-
-target_include_directories(grpc_csharp_ext
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-)
-
-target_link_libraries(grpc_csharp_ext
-  grpc
-  gpr
-)
-
-
-  
-if (gRPC_INSTALL)
-  install(TARGETS grpc_csharp_ext EXPORT gRPCTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  )
-endif()
-
 
 
 add_executable(gen_hpack_tables
diff --git a/Makefile b/Makefile
index 208a7b06e19f3fe8db5024bc02ee72b44f617439..1077332633960108cee2fdfcfc900e54ff2d6824 100644
--- a/Makefile
+++ b/Makefile
@@ -292,12 +292,19 @@ AR = libtool -no_warning_for_no_symbols -o
 endif
 STRIP ?= strip -x
 else
+ifeq ($(SYSTEM),MINGW32)
+ifeq ($(origin AR), default)
+AR = ar rcs
+endif
+STRIP ?= strip --strip-unneeded
+else
 ifeq ($(origin AR), default)
 AR = ar rcs
 endif
 STRIP ?= strip
 endif
 endif
+endif
 INSTALL ?= install
 RM ?= rm -f
 PKG_CONFIG ?= pkg-config
@@ -479,6 +486,7 @@ CPP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix
 CSHARP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(CSHARP_VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE)
 
 ifeq ($(SYSTEM),MINGW32)
+EXECUTABLE_SUFFIX = .exe
 SHARED_EXT_CORE = dll
 SHARED_EXT_CPP = dll
 SHARED_EXT_CSHARP = dll
@@ -487,6 +495,7 @@ SHARED_VERSION_CORE = -2
 SHARED_VERSION_CPP = -1
 SHARED_VERSION_CSHARP = -1
 else ifeq ($(SYSTEM),Darwin)
+EXECUTABLE_SUFFIX = 
 SHARED_EXT_CORE = dylib
 SHARED_EXT_CPP = dylib
 SHARED_EXT_CSHARP = dylib
@@ -495,6 +504,7 @@ SHARED_VERSION_CORE =
 SHARED_VERSION_CPP =
 SHARED_VERSION_CSHARP =
 else
+EXECUTABLE_SUFFIX = 
 SHARED_EXT_CORE = so.$(CORE_VERSION)
 SHARED_EXT_CPP = so.$(CPP_VERSION)
 SHARED_EXT_CSHARP = so.$(CSHARP_VERSION)
@@ -1085,6 +1095,7 @@ grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
 grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test
 grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
 grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test
+http2_client: $(BINDIR)/$(CONFIG)/http2_client
 hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
@@ -1260,9 +1271,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
 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.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.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_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_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_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.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_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_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_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 else
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.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.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
 endif
 
 
@@ -1467,6 +1478,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/grpc_tool_test \
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
@@ -1560,6 +1572,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/grpc_tool_test \
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
@@ -2039,7 +2052,7 @@ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_ba
 $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2054,7 +2067,7 @@ $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc: src/proto/grpc/ref
 $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2069,7 +2082,7 @@ $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: src/proto/grpc/testing/com
 $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2084,7 +2097,7 @@ $(GENDIR)/src/proto/grpc/testing/control.pb.cc: src/proto/grpc/testing/control.p
 $(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
 	$(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2099,7 +2112,7 @@ $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc: src/proto/grpc/
 $(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
 	$(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2114,7 +2127,7 @@ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc: src/proto/grpc/testing/echo.proto $
 $(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
 	$(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2129,7 +2142,7 @@ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc: src/proto/grpc/testing/ech
 $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2144,7 +2157,7 @@ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc: src/proto/grpc/testing/empty.proto
 $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2159,7 +2172,7 @@ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc: src/proto/grpc/testing/messages
 $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2174,7 +2187,7 @@ $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc: src/proto/grpc/testing/metrics.p
 $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2189,7 +2202,7 @@ $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc: src/proto/grpc/testing/payloads
 $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2204,7 +2217,7 @@ $(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services
 $(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
 	$(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2219,7 +2232,7 @@ $(GENDIR)/src/proto/grpc/testing/stats.pb.cc: src/proto/grpc/testing/stats.proto
 $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 ifeq ($(NO_PROTOC),true)
@@ -2234,7 +2247,7 @@ $(GENDIR)/src/proto/grpc/testing/test.pb.cc: src/proto/grpc/testing/test.proto $
 $(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
 	$(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 $<
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
 
@@ -2327,7 +2340,7 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
 install-shared_c: shared_c strip-shared_c install-pkg-config_c
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr-imp.a $(prefix)/lib/libgpr-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2336,7 +2349,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc-imp.a $(prefix)/lib/libgrpc-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2345,7 +2358,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet-imp.a $(prefix)/lib/libgrpc_cronet-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2354,7 +2367,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure-imp.a $(prefix)/lib/libgrpc_unsecure-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2371,7 +2384,7 @@ endif
 install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-config_cxx
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++-imp.a $(prefix)/lib/libgrpc++-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2380,7 +2393,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet-imp.a $(prefix)/lib/libgrpc++_cronet-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2389,7 +2402,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection-imp.a $(prefix)/lib/libgrpc++_reflection-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2398,7 +2411,7 @@ else ifneq ($(SYSTEM),Darwin)
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2415,7 +2428,7 @@ endif
 install-shared_csharp: shared_csharp strip-shared_csharp
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP)
+	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a
 else ifneq ($(SYSTEM),Darwin)
@@ -2430,9 +2443,6 @@ endif
 
 
 install-plugins: $(PROTOC_PLUGINS)
-ifeq ($(SYSTEM),MINGW32)
-	$(Q) false
-else
 	$(E) "[INSTALL] Installing grpc protoc plugins"
 	$(Q) $(INSTALL) -d $(prefix)/bin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin
@@ -2448,7 +2458,6 @@ else
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin
 	$(Q) $(INSTALL) -d $(prefix)/bin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin
-endif
 
 install-pkg-config_c: pc_c pc_c_unsecure
 	$(E) "[INSTALL] Installing C pkg-config files"
@@ -2579,17 +2588,17 @@ ifeq ($(SYSTEM),MINGW32)
 $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS)  $(ZLIB_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared gpr.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS)
 else
 $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS)  $(ZLIB_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS)
 else
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.2 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
 endif
 endif
 
@@ -2632,6 +2641,8 @@ LIBGRPC_SRC = \
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
@@ -2901,17 +2912,17 @@ ifeq ($(SYSTEM),MINGW32)
 $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
 else
 $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
 else
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
 endif
 endif
 
@@ -2933,6 +2944,8 @@ LIBGRPC_CRONET_SRC = \
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
@@ -3173,17 +3186,17 @@ ifeq ($(SYSTEM),MINGW32)
 $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_cronet.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
 else
 $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
 else
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so
 endif
 endif
 
@@ -3224,6 +3237,8 @@ LIBGRPC_TEST_UTIL_SRC = \
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
@@ -3443,6 +3458,8 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
@@ -3671,17 +3688,17 @@ ifeq ($(SYSTEM),MINGW32)
 $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_unsecure.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
 else
 $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
 else
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
 endif
 endif
 
@@ -3933,20 +3950,20 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++.def -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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp
+	$(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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp
 else
 $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(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).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc
 else
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
+	$(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
 endif
 
@@ -4026,6 +4043,8 @@ LIBGRPC++_CRONET_SRC = \
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
@@ -4307,20 +4326,20 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_cronet.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp
 else
 $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(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++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet
 else
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
 endif
 endif
 
@@ -4430,20 +4449,20 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_reflection.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp
 else
 $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++
 else
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so
 endif
 endif
 
@@ -4824,20 +4843,20 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT_CORE)
+$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_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 grpc++_unsecure.def -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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp
+	$(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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp
 else
 $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_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).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure
+	$(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) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure
 else
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
+	$(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
 endif
 
@@ -4951,6 +4970,59 @@ ifneq ($(NO_DEPS),true)
 endif
 
 
+LIBHTTP2_CLIENT_MAIN_SRC = \
+    $(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.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \
+    test/cpp/interop/http2_client.cc \
+
+PUBLIC_HEADERS_CXX += \
+
+LIBHTTP2_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBHTTP2_CLIENT_MAIN_SRC))))
+
+
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure libraries if you don't have OpenSSL.
+
+$(LIBDIR)/$(CONFIG)/libhttp2_client_main.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)/libhttp2_client_main.a: protobuf_dep_error
+
+
+else
+
+$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBHTTP2_CLIENT_MAIN_OBJS) 
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a
+	$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBHTTP2_CLIENT_MAIN_OBJS) 
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a
+endif
+
+
+
+
+endif
+
+endif
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LIBHTTP2_CLIENT_MAIN_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/http2_client.o: $(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.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
+
+
 LIBINTEROP_CLIENT_HELPER_SRC = \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     test/cpp/interop/client_helper.cc \
@@ -5317,17 +5389,17 @@ ifeq ($(SYSTEM),MINGW32)
 $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared grpc_csharp_ext.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
 else
 $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
+	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
 else
 	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so
 endif
 endif
 
@@ -12905,6 +12977,37 @@ endif
 $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http2_client: 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)/http2_client: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/http2_client:  $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/http2_client
+
+endif
+
+endif
+
+
+
+
 HYBRID_END2END_TEST_SRC = \
     test/cpp/end2end/hybrid_end2end_test.cc \
 
@@ -16822,6 +16925,7 @@ test/core/util/test_tcp_server.c: $(OPENSSL_DEP)
 test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP)
 test/cpp/interop/client.cc: $(OPENSSL_DEP)
 test/cpp/interop/client_helper.cc: $(OPENSSL_DEP)
+test/cpp/interop/http2_client.cc: $(OPENSSL_DEP)
 test/cpp/interop/interop_client.cc: $(OPENSSL_DEP)
 test/cpp/interop/interop_server.cc: $(OPENSSL_DEP)
 test/cpp/interop/interop_server_bootstrap.cc: $(OPENSSL_DEP)
diff --git a/README.md b/README.md
index 70cf9fcc30e2e4f00d42480adb74412d94b2a0f9..174e861f5945fd9a4bd81e14c5ca4252b59bad41 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,8 @@ See [INSTALL](INSTALL.md) for installation instructions for various platforms.
 
 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.
+
 #Repository Structure & Status
 
 This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core).
diff --git a/binding.gyp b/binding.gyp
index 516cbdce5dc9f2c325c2e3548708938d69c58c31..3a80402c0622117fc3fe9d0141c1069e618a1715 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -572,6 +572,8 @@
         'src/core/lib/channel/connected_channel.c',
         'src/core/lib/channel/deadline_filter.c',
         'src/core/lib/channel/handshaker.c',
+        'src/core/lib/channel/handshaker_factory.c',
+        'src/core/lib/channel/handshaker_registry.c',
         'src/core/lib/channel/http_client_filter.c',
         'src/core/lib/channel/http_server_filter.c',
         'src/core/lib/channel/message_size_filter.c',
diff --git a/build.yaml b/build.yaml
index 289f2a8efd7b7d21a6e8e83cd3403df0ea758d26..3d6353d2e7850ef241c7b28b88cbbdd50ba5a947 100644
--- a/build.yaml
+++ b/build.yaml
@@ -172,6 +172,8 @@ filegroups:
   - src/core/lib/channel/context.h
   - src/core/lib/channel/deadline_filter.h
   - src/core/lib/channel/handshaker.h
+  - src/core/lib/channel/handshaker_factory.h
+  - src/core/lib/channel/handshaker_registry.h
   - src/core/lib/channel/http_client_filter.h
   - src/core/lib/channel/http_server_filter.h
   - src/core/lib/channel/message_size_filter.h
@@ -270,6 +272,8 @@ filegroups:
   - src/core/lib/channel/connected_channel.c
   - src/core/lib/channel/deadline_filter.c
   - src/core/lib/channel/handshaker.c
+  - src/core/lib/channel/handshaker_factory.c
+  - src/core/lib/channel/handshaker_registry.c
   - src/core/lib/channel/http_client_filter.c
   - src/core/lib/channel/http_server_filter.c
   - src/core/lib/channel/message_size_filter.c
@@ -1214,6 +1218,22 @@ libs:
   vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
   vs_props:
   - protoc
+- name: http2_client_main
+  build: private
+  language: c++
+  headers:
+  - test/cpp/interop/http2_client.h
+  src:
+  - src/proto/grpc/testing/empty.proto
+  - src/proto/grpc/testing/messages.proto
+  - src/proto/grpc/testing/test.proto
+  - test/cpp/interop/http2_client.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - grpc++_test_config
 - name: interop_client_helper
   build: private
   language: c++
@@ -1256,6 +1276,7 @@ libs:
   src:
   - test/cpp/interop/server_helper.cc
   deps:
+  - grpc++_test_util
   - grpc_test_util
   - grpc++
   - grpc
@@ -3188,6 +3209,22 @@ targets:
   - grpc++
   - grpc++_test_util
   - grpc_test_util
+- name: http2_client
+  build: test
+  run: false
+  language: c++
+  src: []
+  deps:
+  - http2_client_main
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - grpc++_test_config
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: hybrid_end2end_test
   gtest: true
   build: test
diff --git a/config.m4 b/config.m4
index 4b86e25581d098272adda575a2b75cdd1e078e07..85549e5f4270cd07b503ab6b9d0dfeb77c2ed1e3 100644
--- a/config.m4
+++ b/config.m4
@@ -5,9 +5,9 @@ if test "$PHP_GRPC" != "no"; then
   dnl Write more examples of tests here...
 
   dnl # --with-grpc -> add include path
-  PHP_ADD_INCLUDE(../../grpc/include)
-  PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc)
-  PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include)
+  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
+  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
+  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
 
   LIBS="-lpthread $LIBS"
 
@@ -88,6 +88,8 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/channel/connected_channel.c \
     src/core/lib/channel/deadline_filter.c \
     src/core/lib/channel/handshaker.c \
+    src/core/lib/channel/handshaker_factory.c \
+    src/core/lib/channel/handshaker_registry.c \
     src/core/lib/channel/http_client_filter.c \
     src/core/lib/channel/http_server_filter.c \
     src/core/lib/channel/message_size_filter.c \
diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md
index 5ea3a96dff108a38270ff0fb521fb7bdd7a5944b..b64fe6a024d6f06658b93cf5461e1db73d62ee89 100644
--- a/doc/negative-http2-interop-test-descriptions.md
+++ b/doc/negative-http2-interop-test-descriptions.md
@@ -49,7 +49,8 @@ server. The client should handle the goaway by switching to a new stream without
 the user application having to do a thing.
 
 Client Procedure:
- 1. Client sends two UnaryCall requests with:
+ 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between).
+ TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep
  
     ```
     {
@@ -61,14 +62,14 @@ Client Procedure:
     ```
 
 Client asserts:
-* Call was successful.
+* Both calls are successful.
 * Response payload body is 314159 bytes in size.
 
 Server Procedure:
   1. Server sends a GOAWAY after receiving the first UnaryCall.
 
 Server asserts:
-* The second UnaryCall has a different stream_id than the first one.
+* Two different connections were used from the client.
 
 ### rst_after_header
 
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 57b714b85521e5dba3cc0736b6bbdced0feb4011..1eb178931dcc1cdbb9be8a90e90f82e56c165581 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -258,6 +258,8 @@ Pod::Spec.new do |s|
                       'src/core/lib/channel/context.h',
                       'src/core/lib/channel/deadline_filter.h',
                       'src/core/lib/channel/handshaker.h',
+                      'src/core/lib/channel/handshaker_factory.h',
+                      'src/core/lib/channel/handshaker_registry.h',
                       'src/core/lib/channel/http_client_filter.h',
                       'src/core/lib/channel/http_server_filter.h',
                       'src/core/lib/channel/message_size_filter.h',
@@ -438,6 +440,8 @@ Pod::Spec.new do |s|
                       'src/core/lib/channel/connected_channel.c',
                       'src/core/lib/channel/deadline_filter.c',
                       'src/core/lib/channel/handshaker.c',
+                      'src/core/lib/channel/handshaker_factory.c',
+                      'src/core/lib/channel/handshaker_registry.c',
                       'src/core/lib/channel/http_client_filter.c',
                       'src/core/lib/channel/http_server_filter.c',
                       'src/core/lib/channel/message_size_filter.c',
@@ -666,6 +670,8 @@ Pod::Spec.new do |s|
                               'src/core/lib/channel/context.h',
                               'src/core/lib/channel/deadline_filter.h',
                               'src/core/lib/channel/handshaker.h',
+                              'src/core/lib/channel/handshaker_factory.h',
+                              'src/core/lib/channel/handshaker_registry.h',
                               'src/core/lib/channel/http_client_filter.h',
                               'src/core/lib/channel/http_server_filter.h',
                               'src/core/lib/channel/message_size_filter.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 0515f1e2628c9396ce3f760247c8a38896f621fc..cfc0c35aa3ef75148db6fb26765fc5ec6b50f87c 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -175,6 +175,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/channel/context.h )
   s.files += %w( src/core/lib/channel/deadline_filter.h )
   s.files += %w( src/core/lib/channel/handshaker.h )
+  s.files += %w( src/core/lib/channel/handshaker_factory.h )
+  s.files += %w( src/core/lib/channel/handshaker_registry.h )
   s.files += %w( src/core/lib/channel/http_client_filter.h )
   s.files += %w( src/core/lib/channel/http_server_filter.h )
   s.files += %w( src/core/lib/channel/message_size_filter.h )
@@ -355,6 +357,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/channel/connected_channel.c )
   s.files += %w( src/core/lib/channel/deadline_filter.c )
   s.files += %w( src/core/lib/channel/handshaker.c )
+  s.files += %w( src/core/lib/channel/handshaker_factory.c )
+  s.files += %w( src/core/lib/channel/handshaker_registry.c )
   s.files += %w( src/core/lib/channel/http_client_filter.c )
   s.files += %w( src/core/lib/channel/http_server_filter.c )
   s.files += %w( src/core/lib/channel/message_size_filter.c )
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index cd989d664ca0c7bbb219a79879fb7ca307336c72..4633fa12e84767d836b53b245024387759579992 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -361,7 +361,7 @@ typedef unsigned __int64 uint64_t;
 #define GPR_MAX_ALIGNMENT 16
 
 #ifndef GRPC_MUST_USE_RESULT
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__MINGW32__)
 #define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result))
 #else
 #define GRPC_MUST_USE_RESULT
diff --git a/include/grpc/support/log_windows.h b/include/grpc/support/log_windows.h
index 12bf8cc1f5ecea5c1d88e8ce60906c34ad51c9f2..943a8e908b3eea1a4d121d148e30eec041303a3f 100644
--- a/include/grpc/support/log_windows.h
+++ b/include/grpc/support/log_windows.h
@@ -34,6 +34,8 @@
 #ifndef GRPC_SUPPORT_LOG_WINDOWS_H
 #define GRPC_SUPPORT_LOG_WINDOWS_H
 
+#include <grpc/impl/codegen/port_platform.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/package.json b/package.json
index 5506e9bbdf8deaba326801fb5c635bae7608ea71..6fd799cbab0971f3911cb149d4d0de01fe5da3f3 100644
--- a/package.json
+++ b/package.json
@@ -50,7 +50,7 @@
     "poisson-process": "^0.2.1"
   },
   "engines": {
-    "node": ">=0.12.0"
+    "node": ">=1.1.0"
   },
   "binary": {
     "module_name": "grpc_node",
diff --git a/package.xml b/package.xml
index c35cf408278402765b03834fbba7f876545485bd..a2028ce642409d69beb2fdf79743f8a17531dc78 100644
--- a/package.xml
+++ b/package.xml
@@ -183,6 +183,8 @@
     <file baseinstalldir="/" name="src/core/lib/channel/context.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/deadline_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/handshaker.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/handshaker_factory.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/message_size_filter.h" role="src" />
@@ -363,6 +365,8 @@
     <file baseinstalldir="/" name="src/core/lib/channel/connected_channel.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/deadline_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/handshaker.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/handshaker_factory.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/message_size_filter.c" role="src" />
diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c
index 8f0e12296ddc13b7b7a8608f7efe462f26744fe0..3b5d6dab2b8d775f1624e5f922f9f692e66b98ea 100644
--- a/src/core/ext/census/tracing.c
+++ b/src/core/ext/census/tracing.c
@@ -31,19 +31,15 @@
  *
  */
 
-//#include "src/core/ext/census/tracing.h"
-
 #include <grpc/census.h>
 
 /* TODO(aveitch): These are all placeholder implementations. */
 
-// int census_trace_mask(const census_context *context) {
-//   return CENSUS_TRACE_MASK_NONE;
-// }
-
-// void census_set_trace_mask(int trace_mask) {}
+int census_trace_mask(const census_context *context) {
+  return CENSUS_TRACE_MASK_NONE;
+}
 
-// void census_trace_print(census_context *context, uint32_t type,
-//                         const char *buffer, size_t n) {}
+void census_set_trace_mask(int trace_mask) {}
 
-// void SetTracerParams(const Params& params);
+void census_trace_print(census_context *context, uint32_t type,
+                        const char *buffer, size_t n) {}
diff --git a/src/core/ext/client_channel/client_channel_plugin.c b/src/core/ext/client_channel/client_channel_plugin.c
index 988b7a1d5c86b64eeb50d8b27ca6cad25c1f6841..d50bba60f6a28a0cb201d00013c2c60b708d15f1 100644
--- a/src/core/ext/client_channel/client_channel_plugin.c
+++ b/src/core/ext/client_channel/client_channel_plugin.c
@@ -38,6 +38,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/client_channel/subchannel_index.h"
@@ -84,6 +85,7 @@ void grpc_client_channel_init(void) {
                                    set_default_host_if_unset, NULL);
   grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, append_filter,
                                    (void *)&grpc_client_channel_filter);
+  grpc_http_connect_register_handshaker_factory();
 }
 
 void grpc_client_channel_shutdown(void) {
diff --git a/src/core/ext/client_channel/http_connect_handshaker.c b/src/core/ext/client_channel/http_connect_handshaker.c
index 27b117af84ab59c96634fcdac08bd615845c6bbd..fba32561acf822b04c776ced5815df6c8a98d0cc 100644
--- a/src/core/ext/client_channel/http_connect_handshaker.c
+++ b/src/core/ext/client_channel/http_connect_handshaker.c
@@ -44,6 +44,7 @@
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/client_channel/uri_parser.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/http/format_request.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/slice/slice_internal.h"
@@ -54,6 +55,8 @@ typedef struct http_connect_handshaker {
   grpc_handshaker base;
 
   char* proxy_server;
+  grpc_http_header* headers;
+  size_t num_headers;
 
   gpr_refcount refcount;
   gpr_mu mu;
@@ -89,6 +92,11 @@ static void http_connect_handshaker_unref(grpc_exec_ctx* exec_ctx,
       gpr_free(handshaker->read_buffer_to_destroy);
     }
     gpr_free(handshaker->proxy_server);
+    for (size_t i = 0; i < handshaker->num_headers; ++i) {
+      gpr_free(handshaker->headers[i].key);
+      gpr_free(handshaker->headers[i].value);
+    }
+    gpr_free(handshaker->headers);
     grpc_slice_buffer_destroy_internal(exec_ctx, &handshaker->write_buffer);
     grpc_http_parser_destroy(&handshaker->http_parser);
     grpc_http_response_destroy(&handshaker->http_response);
@@ -289,6 +297,8 @@ static void http_connect_handshaker_do_handshake(
   request.host = server_name;
   request.http.method = "CONNECT";
   request.http.path = server_name;
+  request.http.hdrs = handshaker->headers;
+  request.http.hdr_count = handshaker->num_headers;
   request.handshaker = &grpc_httpcli_plaintext;
   grpc_slice request_slice = grpc_httpcli_format_connect_request(&request);
   grpc_slice_buffer_add(&handshaker->write_buffer, request_slice);
@@ -306,7 +316,9 @@ static const grpc_handshaker_vtable http_connect_handshaker_vtable = {
     http_connect_handshaker_destroy, http_connect_handshaker_shutdown,
     http_connect_handshaker_do_handshake};
 
-grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server) {
+grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server,
+                                                     grpc_http_header* headers,
+                                                     size_t num_headers) {
   GPR_ASSERT(proxy_server != NULL);
   http_connect_handshaker* handshaker = gpr_malloc(sizeof(*handshaker));
   memset(handshaker, 0, sizeof(*handshaker));
@@ -314,6 +326,14 @@ grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server) {
   gpr_mu_init(&handshaker->mu);
   gpr_ref_init(&handshaker->refcount, 1);
   handshaker->proxy_server = gpr_strdup(proxy_server);
+  if (num_headers > 0) {
+    handshaker->headers = gpr_malloc(sizeof(grpc_http_header) * num_headers);
+    for (size_t i = 0; i < num_headers; ++i) {
+      handshaker->headers[i].key = gpr_strdup(headers[i].key);
+      handshaker->headers[i].value = gpr_strdup(headers[i].value);
+    }
+    handshaker->num_headers = num_headers;
+  }
   grpc_slice_buffer_init(&handshaker->write_buffer);
   grpc_closure_init(&handshaker->request_done_closure, on_write_done,
                     handshaker, grpc_schedule_on_exec_ctx);
@@ -347,3 +367,33 @@ done:
   grpc_uri_destroy(uri);
   return proxy_name;
 }
+
+//
+// handshaker factory
+//
+
+static void handshaker_factory_add_handshakers(
+    grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* factory,
+    const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) {
+  char* proxy_name = grpc_get_http_proxy_server();
+  if (proxy_name != NULL) {
+    grpc_handshake_manager_add(
+        handshake_mgr,
+        grpc_http_connect_handshaker_create(proxy_name, NULL, 0));
+    gpr_free(proxy_name);
+  }
+}
+
+static void handshaker_factory_destroy(grpc_exec_ctx* exec_ctx,
+                                       grpc_handshaker_factory* factory) {}
+
+static const grpc_handshaker_factory_vtable handshaker_factory_vtable = {
+    handshaker_factory_add_handshakers, handshaker_factory_destroy};
+
+static grpc_handshaker_factory handshaker_factory = {
+    &handshaker_factory_vtable};
+
+void grpc_http_connect_register_handshaker_factory() {
+  grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_CLIENT,
+                                   &handshaker_factory);
+}
diff --git a/src/core/ext/client_channel/http_connect_handshaker.h b/src/core/ext/client_channel/http_connect_handshaker.h
index ea293852e60bc83671e8b5c99c341ab390c5443c..c2e68de7167bff20cb65b033268a519886f5cc74 100644
--- a/src/core/ext/client_channel/http_connect_handshaker.h
+++ b/src/core/ext/client_channel/http_connect_handshaker.h
@@ -35,12 +35,18 @@
 #define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H
 
 #include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/http/parser.h"
 
-/// Does NOT take ownership of \a proxy_server.
-grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server);
+/// Creates a new HTTP CONNECT handshaker.
+grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server,
+                                                     grpc_http_header* headers,
+                                                     size_t num_headers);
 
 /// Returns the name of the proxy to use, or NULL if no proxy is configured.
 /// Caller takes ownership of result.
 char* grpc_get_http_proxy_server();
 
+/// Registers handshaker factory.
+void grpc_http_connect_register_handshaker_factory();
+
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H */
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index bb2b01250729152f6eaa3a0ec6849f8a02dff98f..655d9dc586c2182631b4c2263522875538059f2f 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -189,7 +189,7 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
     gpr_timespec timeout = gpr_time_sub(next_try, now);
     const char *msg = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
+    gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", msg);
     grpc_error_free_string(msg);
     GPR_ASSERT(!r->have_retry_timer);
     r->have_retry_timer = true;
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c
index 2385f91dbd0e89116c20d9d742479e00ae940907..2c5dfaea601c064e83792f576d740c4327bd0463 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.c
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c
@@ -46,6 +46,7 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/slice/slice_internal.h"
 
@@ -58,9 +59,6 @@ typedef struct {
   bool shutdown;
   bool connecting;
 
-  grpc_chttp2_add_handshakers_func add_handshakers;
-  void *add_handshakers_user_data;
-
   grpc_closure *notify;
   grpc_connect_in_args args;
   grpc_connect_out_args *result;
@@ -151,16 +149,8 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
 static void start_handshake_locked(grpc_exec_ctx *exec_ctx,
                                    chttp2_connector *c) {
   c->handshake_mgr = grpc_handshake_manager_create();
-  char *proxy_name = grpc_get_http_proxy_server();
-  if (proxy_name != NULL) {
-    grpc_handshake_manager_add(c->handshake_mgr,
-                               grpc_http_connect_handshaker_create(proxy_name));
-    gpr_free(proxy_name);
-  }
-  if (c->add_handshakers != NULL) {
-    c->add_handshakers(exec_ctx, c->add_handshakers_user_data,
+  grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, c->args.channel_args,
                        c->handshake_mgr);
-  }
   grpc_handshake_manager_do_handshake(
       exec_ctx, c->handshake_mgr, c->endpoint, c->args.channel_args,
       c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
@@ -250,15 +240,11 @@ static const grpc_connector_vtable chttp2_connector_vtable = {
     chttp2_connector_ref, chttp2_connector_unref, chttp2_connector_shutdown,
     chttp2_connector_connect};
 
-grpc_connector *grpc_chttp2_connector_create(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_add_handshakers_func add_handshakers,
-    void *add_handshakers_user_data) {
+grpc_connector *grpc_chttp2_connector_create() {
   chttp2_connector *c = gpr_malloc(sizeof(*c));
   memset(c, 0, sizeof(*c));
   c->base.vtable = &chttp2_connector_vtable;
   gpr_mu_init(&c->mu);
   gpr_ref_init(&c->refs, 1);
-  c->add_handshakers = add_handshakers;
-  c->add_handshakers_user_data = add_handshakers_user_data;
   return &c->base;
 }
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.h b/src/core/ext/transport/chttp2/client/chttp2_connector.h
index 58eba22417847bed380297fcabb3b1a5d59bca39..f5d10254320e4f2a1d7fd70f79efa8f2aabfddc8 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.h
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.h
@@ -35,17 +35,7 @@
 #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H
 
 #include "src/core/ext/client_channel/connector.h"
-#include "src/core/lib/channel/handshaker.h"
-#include "src/core/lib/iomgr/exec_ctx.h"
 
-typedef void (*grpc_chttp2_add_handshakers_func)(
-    grpc_exec_ctx* exec_ctx, void* user_data,
-    grpc_handshake_manager* handshake_mgr);
-
-/// If \a add_handshakers is non-NULL, it will be called with
-/// \a add_handshakers_user_data to add handshakers.
-grpc_connector* grpc_chttp2_connector_create(
-    grpc_exec_ctx* exec_ctx, grpc_chttp2_add_handshakers_func add_handshakers,
-    void* add_handshakers_user_data);
+grpc_connector* grpc_chttp2_connector_create();
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H */
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index 1d3592ef063f3560803b7131382a1fc0a3213c40..c9f4021216e1eb5c60ae54f7d90be8f61464ad6f 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -53,8 +53,7 @@ static void client_channel_factory_unref(
 static grpc_subchannel *client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const grpc_subchannel_args *args) {
-  grpc_connector *connector = grpc_chttp2_connector_create(
-      exec_ctx, NULL /* add_handshakers */, NULL /* user_data */);
+  grpc_connector *connector = grpc_chttp2_connector_create();
   grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args);
   grpc_connector_unref(exec_ctx, connector);
   return s;
@@ -96,17 +95,16 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
       "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3,
       (target, args, reserved));
   GPR_ASSERT(reserved == NULL);
-  grpc_client_channel_factory *factory =
-      (grpc_client_channel_factory *)&client_channel_factory;
   // Add channel arg containing the client channel factory.
-  grpc_arg arg = grpc_client_channel_factory_create_channel_arg(factory);
+  grpc_arg arg =
+      grpc_client_channel_factory_create_channel_arg(&client_channel_factory);
   grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
   // Create channel.
   grpc_channel *channel = client_channel_factory_create_channel(
-      &exec_ctx, factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
+      &exec_ctx, &client_channel_factory, target,
+      GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
   // Clean up.
   grpc_channel_args_destroy(&exec_ctx, new_args);
-  grpc_client_channel_factory_unref(&exec_ctx, factory);
   grpc_exec_ctx_finish(&exec_ctx);
   return channel != NULL ? channel : grpc_lame_client_channel_create(
                                          target, GRPC_STATUS_INTERNAL,
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index 54663ef6a41b29417a3ee25c4459ea0921dd666b..f979d9bad5cd6d0f7b6b3995eb8678baed681185 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -46,40 +46,16 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 
-typedef struct {
-  grpc_client_channel_factory base;
-  gpr_refcount refs;
-  grpc_channel_security_connector *security_connector;
-} client_channel_factory;
-
 static void client_channel_factory_ref(
-    grpc_client_channel_factory *cc_factory) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  gpr_ref(&f->refs);
-}
+    grpc_client_channel_factory *cc_factory) {}
 
 static void client_channel_factory_unref(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  if (gpr_unref(&f->refs)) {
-    GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &f->security_connector->base,
-                                  "client_channel_factory");
-    gpr_free(f);
-  }
-}
-
-static void add_handshakers(grpc_exec_ctx *exec_ctx, void *security_connector,
-                            grpc_handshake_manager *handshake_mgr) {
-  grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
-                                                  handshake_mgr);
-}
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
 
 static grpc_subchannel *client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const grpc_subchannel_args *args) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  grpc_connector *connector = grpc_chttp2_connector_create(
-      exec_ctx, add_handshakers, f->security_connector);
+  grpc_connector *connector = grpc_chttp2_connector_create();
   grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args);
   grpc_connector_unref(exec_ctx, connector);
   return s;
@@ -106,6 +82,9 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
      client_channel_factory_create_subchannel,
      client_channel_factory_create_channel};
 
+static grpc_client_channel_factory client_channel_factory = {
+    &client_channel_factory_vtable};
+
 /* Create a secure client channel:
    Asynchronously: - resolve target
                    - connect to it (trying alternatives as presented)
@@ -138,33 +117,26 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
     return grpc_lame_client_channel_create(
         target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
   }
-  // Create client channel factory.
-  client_channel_factory *f = gpr_malloc(sizeof(*f));
-  memset(f, 0, sizeof(*f));
-  f->base.vtable = &client_channel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
-                              "grpc_secure_channel_create");
-  f->security_connector = security_connector;
   // Add channel args containing the client channel factory and security
   // connector.
-  grpc_arg new_args[2];
-  new_args[0] = grpc_client_channel_factory_create_channel_arg(&f->base);
-  new_args[1] = grpc_security_connector_to_arg(&security_connector->base);
-  grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
+  grpc_arg args_to_add[2];
+  args_to_add[0] =
+      grpc_client_channel_factory_create_channel_arg(&client_channel_factory);
+  args_to_add[1] = grpc_security_connector_to_arg(&security_connector->base);
+  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
       new_args_from_connector != NULL ? new_args_from_connector : args,
-      new_args, GPR_ARRAY_SIZE(new_args));
+      args_to_add, GPR_ARRAY_SIZE(args_to_add));
   if (new_args_from_connector != NULL) {
     grpc_channel_args_destroy(&exec_ctx, new_args_from_connector);
   }
   // Create channel.
   grpc_channel *channel = client_channel_factory_create_channel(
-      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, args_copy);
+      &exec_ctx, &client_channel_factory, target,
+      GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
   // Clean up.
-  GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &f->security_connector->base,
+  GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &security_connector->base,
                                 "secure_client_channel_factory_create_channel");
-  grpc_channel_args_destroy(&exec_ctx, args_copy);
-  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
+  grpc_channel_args_destroy(&exec_ctx, new_args);
   grpc_exec_ctx_finish(&exec_ctx);
   return channel; /* may be NULL */
 }
diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.c b/src/core/ext/transport/chttp2/server/chttp2_server.c
index 86f5a198c26f4c0baa0e35e75b449c8a3b258749..574d1a7710195a4c58a0bbd71653755288df2372 100644
--- a/src/core/ext/transport/chttp2/server/chttp2_server.c
+++ b/src/core/ext/transport/chttp2/server/chttp2_server.c
@@ -46,6 +46,7 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/channel/http_server_filter.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/resolve_address.h"
@@ -54,24 +55,6 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-void grpc_chttp2_server_handshaker_factory_add_handshakers(
-    grpc_exec_ctx *exec_ctx,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory,
-    grpc_handshake_manager *handshake_mgr) {
-  if (handshaker_factory != NULL) {
-    handshaker_factory->vtable->add_handshakers(exec_ctx, handshaker_factory,
-                                                handshake_mgr);
-  }
-}
-
-void grpc_chttp2_server_handshaker_factory_destroy(
-    grpc_exec_ctx *exec_ctx,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory) {
-  if (handshaker_factory != NULL) {
-    handshaker_factory->vtable->destroy(exec_ctx, handshaker_factory);
-  }
-}
-
 typedef struct pending_handshake_manager_node {
   grpc_handshake_manager *handshake_mgr;
   struct pending_handshake_manager_node *next;
@@ -81,7 +64,6 @@ typedef struct {
   grpc_server *server;
   grpc_tcp_server *tcp_server;
   grpc_channel_args *args;
-  grpc_chttp2_server_handshaker_factory *handshaker_factory;
   gpr_mu mu;
   bool shutdown;
   grpc_closure tcp_server_shutdown_complete;
@@ -198,8 +180,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
   connection_state->accepting_pollset = accepting_pollset;
   connection_state->acceptor = acceptor;
   connection_state->handshake_mgr = handshake_mgr;
-  grpc_chttp2_server_handshaker_factory_add_handshakers(
-      exec_ctx, state->handshaker_factory, connection_state->handshake_mgr);
+  grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args,
+                       connection_state->handshake_mgr);
   // TODO(roth): We should really get this timeout value from channel
   // args instead of hard-coding it.
   const gpr_timespec deadline = gpr_time_add(
@@ -233,8 +215,6 @@ static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
   // Flush queued work before destroying handshaker factory, since that
   // may do a synchronous unref.
   grpc_exec_ctx_flush(exec_ctx);
-  grpc_chttp2_server_handshaker_factory_destroy(exec_ctx,
-                                                state->handshaker_factory);
   if (destroy_done != NULL) {
     destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
     grpc_exec_ctx_flush(exec_ctx);
@@ -259,10 +239,10 @@ static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
   grpc_tcp_server_unref(exec_ctx, tcp_server);
 }
 
-grpc_error *grpc_chttp2_server_add_port(
-    grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr,
-    grpc_channel_args *args,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory, int *port_num) {
+grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
+                                        grpc_server *server, const char *addr,
+                                        grpc_channel_args *args,
+                                        int *port_num) {
   grpc_resolved_addresses *resolved = NULL;
   grpc_tcp_server *tcp_server = NULL;
   size_t i;
@@ -293,7 +273,6 @@ grpc_error *grpc_chttp2_server_add_port(
   state->server = server;
   state->tcp_server = tcp_server;
   state->args = args;
-  state->handshaker_factory = handshaker_factory;
   state->shutdown = true;
   gpr_mu_init(&state->mu);
 
@@ -348,7 +327,6 @@ error:
     grpc_tcp_server_unref(exec_ctx, tcp_server);
   } else {
     grpc_channel_args_destroy(exec_ctx, args);
-    grpc_chttp2_server_handshaker_factory_destroy(exec_ctx, handshaker_factory);
     gpr_free(state);
   }
   *port_num = 0;
diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.h b/src/core/ext/transport/chttp2/server/chttp2_server.h
index aa364b565d655941485986fc3945a13573bc43b7..2581ebaae9673c429241517630015e7011abcfa4 100644
--- a/src/core/ext/transport/chttp2/server/chttp2_server.h
+++ b/src/core/ext/transport/chttp2/server/chttp2_server.h
@@ -36,43 +36,12 @@
 
 #include <grpc/impl/codegen/grpc_types.h>
 
-#include "src/core/lib/channel/handshaker.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-/// A server handshaker factory is used to create handshakers for server
-/// connections.
-typedef struct grpc_chttp2_server_handshaker_factory
-    grpc_chttp2_server_handshaker_factory;
-
-typedef struct {
-  void (*add_handshakers)(
-      grpc_exec_ctx *exec_ctx,
-      grpc_chttp2_server_handshaker_factory *handshaker_factory,
-      grpc_handshake_manager *handshake_mgr);
-  void (*destroy)(grpc_exec_ctx *exec_ctx,
-                  grpc_chttp2_server_handshaker_factory *handshaker_factory);
-} grpc_chttp2_server_handshaker_factory_vtable;
-
-struct grpc_chttp2_server_handshaker_factory {
-  const grpc_chttp2_server_handshaker_factory_vtable *vtable;
-};
-
-void grpc_chttp2_server_handshaker_factory_add_handshakers(
-    grpc_exec_ctx *exec_ctx,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory,
-    grpc_handshake_manager *handshake_mgr);
-
-void grpc_chttp2_server_handshaker_factory_destroy(
-    grpc_exec_ctx *exec_ctx,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory);
-
 /// Adds a port to \a server.  Sets \a port_num to the port number.
-/// If \a handshaker_factory is not NULL, it will be used to create
-/// handshakers for the port.
-/// Takes ownership of \a args and \a handshaker_factory.
-grpc_error *grpc_chttp2_server_add_port(
-    grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr,
-    grpc_channel_args *args,
-    grpc_chttp2_server_handshaker_factory *handshaker_factory, int *port_num);
+/// Takes ownership of \a args.
+grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
+                                        grpc_server *server, const char *addr,
+                                        grpc_channel_args *args, int *port_num);
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
index 7e286d4e46d51421bd8436007eff67881ca29e46..bf5026bea643c55bf2f2a49eae2aa32a78390109 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -47,8 +47,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
                  (server, addr));
   grpc_error *err = grpc_chttp2_server_add_port(
       &exec_ctx, server, addr,
-      grpc_channel_args_copy(grpc_server_get_channel_args(server)),
-      NULL /* handshaker_factory */, &port_num);
+      grpc_channel_args_copy(grpc_server_get_channel_args(server)), &port_num);
   if (err != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(err);
     gpr_log(GPR_ERROR, "%s", msg);
diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
index b5e4996b16ea6eae1b6fce2f46bdb4eb3b3685b5..395c79a71d13af47df569e8218cae30b0ba253e0 100644
--- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -49,34 +49,6 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-typedef struct {
-  grpc_chttp2_server_handshaker_factory base;
-  grpc_server_security_connector *security_connector;
-} server_security_handshaker_factory;
-
-static void server_security_handshaker_factory_add_handshakers(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_server_handshaker_factory *hf,
-    grpc_handshake_manager *handshake_mgr) {
-  server_security_handshaker_factory *handshaker_factory =
-      (server_security_handshaker_factory *)hf;
-  grpc_server_security_connector_add_handshakers(
-      exec_ctx, handshaker_factory->security_connector, handshake_mgr);
-}
-
-static void server_security_handshaker_factory_destroy(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_server_handshaker_factory *hf) {
-  server_security_handshaker_factory *handshaker_factory =
-      (server_security_handshaker_factory *)hf;
-  GRPC_SECURITY_CONNECTOR_UNREF(
-      exec_ctx, &handshaker_factory->security_connector->base, "server");
-  gpr_free(hf);
-}
-
-static const grpc_chttp2_server_handshaker_factory_vtable
-    server_security_handshaker_factory_vtable = {
-        server_security_handshaker_factory_add_handshakers,
-        server_security_handshaker_factory_destroy};
-
 int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
                                       grpc_server_credentials *creds) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -105,20 +77,19 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
     gpr_free(msg);
     goto done;
   }
-  // Create handshaker factory.
-  server_security_handshaker_factory *handshaker_factory =
-      gpr_malloc(sizeof(*handshaker_factory));
-  memset(handshaker_factory, 0, sizeof(*handshaker_factory));
-  handshaker_factory->base.vtable = &server_security_handshaker_factory_vtable;
-  handshaker_factory->security_connector = sc;
   // Create channel args.
-  grpc_arg channel_arg = grpc_server_credentials_to_arg(creds);
-  grpc_channel_args *args = grpc_channel_args_copy_and_add(
-      grpc_server_get_channel_args(server), &channel_arg, 1);
+  grpc_arg args_to_add[2];
+  args_to_add[0] = grpc_server_credentials_to_arg(creds);
+  args_to_add[1] = grpc_security_connector_to_arg(&sc->base);
+  grpc_channel_args *args =
+      grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server),
+                                     args_to_add, GPR_ARRAY_SIZE(args_to_add));
   // Add server port.
-  err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args,
-                                    &handshaker_factory->base, &port_num);
+  err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args, &port_num);
 done:
+  if (sc != NULL) {
+    GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "server");
+  }
   grpc_exec_ctx_finish(&exec_ctx);
   if (err != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(err);
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
index b4c5ed769b9cf0cc689411454738125bfe17033c..20043f5fbf431cd9a275cf6e3ae782b6b7e4fc98 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
@@ -109,7 +109,7 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx,
                       (((uint32_t)p->reason_bytes[2]) << 8) |
                       (((uint32_t)p->reason_bytes[3]));
     grpc_error *error = GRPC_ERROR_NONE;
-    if (reason != GRPC_CHTTP2_NO_ERROR) {
+    if (reason != GRPC_CHTTP2_NO_ERROR || s->header_frames_received < 2) {
       error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"),
                                  GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
       grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
diff --git a/src/core/lib/channel/handshaker_factory.c b/src/core/lib/channel/handshaker_factory.c
new file mode 100644
index 0000000000000000000000000000000000000000..3c30a4e1d2effe1621d80126b1617130ada8e879
--- /dev/null
+++ b/src/core/lib/channel/handshaker_factory.c
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/channel/handshaker_factory.h"
+
+#include <grpc/support/log.h>
+
+void grpc_handshaker_factory_add_handshakers(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
+    const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
+  if (handshaker_factory != NULL) {
+    GPR_ASSERT(handshaker_factory->vtable != NULL);
+    handshaker_factory->vtable->add_handshakers(exec_ctx, handshaker_factory,
+                                                args, handshake_mgr);
+  }
+}
+
+void grpc_handshaker_factory_destroy(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {
+  if (handshaker_factory != NULL) {
+    GPR_ASSERT(handshaker_factory->vtable != NULL);
+    handshaker_factory->vtable->destroy(exec_ctx, handshaker_factory);
+  }
+}
diff --git a/src/core/lib/channel/handshaker_factory.h b/src/core/lib/channel/handshaker_factory.h
new file mode 100644
index 0000000000000000000000000000000000000000..1984546104d37596515e43faaae47ddb26491cbc
--- /dev/null
+++ b/src/core/lib/channel/handshaker_factory.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H
+#define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+// A handshaker factory is used to create handshakers.
+
+typedef struct grpc_handshaker_factory grpc_handshaker_factory;
+
+typedef struct {
+  void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
+                          grpc_handshaker_factory *handshaker_factory,
+                          const grpc_channel_args *args,
+                          grpc_handshake_manager *handshake_mgr);
+  void (*destroy)(grpc_exec_ctx *exec_ctx,
+                  grpc_handshaker_factory *handshaker_factory);
+} grpc_handshaker_factory_vtable;
+
+struct grpc_handshaker_factory {
+  const grpc_handshaker_factory_vtable *vtable;
+};
+
+void grpc_handshaker_factory_add_handshakers(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
+    const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr);
+
+void grpc_handshaker_factory_destroy(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory);
+
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */
diff --git a/src/core/lib/channel/handshaker_registry.c b/src/core/lib/channel/handshaker_registry.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e5f04064c26d2c83d2e55d45129ddffb9f11275
--- /dev/null
+++ b/src/core/lib/channel/handshaker_registry.c
@@ -0,0 +1,113 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/channel/handshaker_registry.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+//
+// grpc_handshaker_factory_list
+//
+
+typedef struct {
+  grpc_handshaker_factory** list;
+  size_t num_factories;
+} grpc_handshaker_factory_list;
+
+static void grpc_handshaker_factory_list_register(
+    grpc_handshaker_factory_list* list, bool at_start,
+    grpc_handshaker_factory* factory) {
+  list->list = gpr_realloc(
+      list->list, (list->num_factories + 1) * sizeof(grpc_handshaker_factory*));
+  if (at_start) {
+    memmove(list->list + 1, list->list,
+            sizeof(grpc_handshaker_factory*) * list->num_factories);
+    list->list[0] = factory;
+  } else {
+    list->list[list->num_factories] = factory;
+  }
+  ++list->num_factories;
+}
+
+static void grpc_handshaker_factory_list_add_handshakers(
+    grpc_exec_ctx* exec_ctx, grpc_handshaker_factory_list* list,
+    const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) {
+  for (size_t i = 0; i < list->num_factories; ++i) {
+    grpc_handshaker_factory_add_handshakers(exec_ctx, list->list[i], args,
+                                            handshake_mgr);
+  }
+}
+
+static void grpc_handshaker_factory_list_destroy(
+    grpc_exec_ctx* exec_ctx, grpc_handshaker_factory_list* list) {
+  for (size_t i = 0; i < list->num_factories; ++i) {
+    grpc_handshaker_factory_destroy(exec_ctx, list->list[i]);
+  }
+  gpr_free(list->list);
+}
+
+//
+// plugin
+//
+
+static grpc_handshaker_factory_list
+    g_handshaker_factory_lists[NUM_HANDSHAKER_TYPES];
+
+void grpc_handshaker_factory_registry_init() {
+  memset(g_handshaker_factory_lists, 0, sizeof(g_handshaker_factory_lists));
+}
+
+void grpc_handshaker_factory_registry_shutdown(grpc_exec_ctx* exec_ctx) {
+  for (size_t i = 0; i < NUM_HANDSHAKER_TYPES; ++i) {
+    grpc_handshaker_factory_list_destroy(exec_ctx,
+                                         &g_handshaker_factory_lists[i]);
+  }
+}
+
+void grpc_handshaker_factory_register(bool at_start,
+                                      grpc_handshaker_type handshaker_type,
+                                      grpc_handshaker_factory* factory) {
+  grpc_handshaker_factory_list_register(
+      &g_handshaker_factory_lists[handshaker_type], at_start, factory);
+}
+
+void grpc_handshakers_add(grpc_exec_ctx* exec_ctx,
+                          grpc_handshaker_type handshaker_type,
+                          const grpc_channel_args* args,
+                          grpc_handshake_manager* handshake_mgr) {
+  grpc_handshaker_factory_list_add_handshakers(
+      exec_ctx, &g_handshaker_factory_lists[handshaker_type], args,
+      handshake_mgr);
+}
diff --git a/src/core/lib/channel/handshaker_registry.h b/src/core/lib/channel/handshaker_registry.h
new file mode 100644
index 0000000000000000000000000000000000000000..53c1b173af230a05d9e60e398f911b10563eed23
--- /dev/null
+++ b/src/core/lib/channel/handshaker_registry.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H
+#define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/channel/handshaker_factory.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+typedef enum {
+  HANDSHAKER_CLIENT = 0,
+  HANDSHAKER_SERVER,
+  NUM_HANDSHAKER_TYPES,  // Must be last.
+} grpc_handshaker_type;
+
+void grpc_handshaker_factory_registry_init();
+void grpc_handshaker_factory_registry_shutdown(grpc_exec_ctx* exec_ctx);
+
+/// Registers a new handshaker factory.  Takes ownership.
+/// If \a at_start is true, the new handshaker will be at the beginning of
+/// the list.  Otherwise, it will be added to the end.
+void grpc_handshaker_factory_register(bool at_start,
+                                      grpc_handshaker_type handshaker_type,
+                                      grpc_handshaker_factory* factory);
+
+void grpc_handshakers_add(grpc_exec_ctx* exec_ctx,
+                          grpc_handshaker_type handshaker_type,
+                          const grpc_channel_args* args,
+                          grpc_handshake_manager* handshake_mgr);
+
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */
diff --git a/src/core/lib/iomgr/iocp_windows.c b/src/core/lib/iomgr/iocp_windows.c
index 60ebe43676dce3b8c4d2549a3003ec6700a91ecf..f0f4a6ff39096b7dcf19fea7d12010a166fa5537 100644
--- a/src/core/lib/iomgr/iocp_windows.c
+++ b/src/core/lib/iomgr/iocp_windows.c
@@ -80,7 +80,6 @@ grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
   LPOVERLAPPED overlapped;
   grpc_winsocket *socket;
   grpc_winsocket_callback_info *info;
-  grpc_closure *closure = NULL;
   success = GetQueuedCompletionStatus(
       g_iocp, &bytes, &completion_key, &overlapped,
       deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 97d78274614ccf63b0b2fc7c7318db2a4a104e48..dafe851ce8b51c7d92fcf4a3773864a4f3c6c9a3 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -184,7 +184,6 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
 }
 
 static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  int immediately_done = 0;
   grpc_tcp_listener *sp;
   gpr_mu_lock(&s->mu);
 
@@ -240,7 +239,7 @@ static grpc_error *prepare_socket(SOCKET sock,
     error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname");
     goto failure;
   }
-  sockname_temp.len = sockname_temp_len;
+  sockname_temp.len = (size_t)sockname_temp_len;
 
   *port = grpc_sockaddr_get_port(&sockname_temp);
   return GRPC_ERROR_NONE;
@@ -248,7 +247,7 @@ static grpc_error *prepare_socket(SOCKET sock,
 failure:
   GPR_ASSERT(error != GRPC_ERROR_NONE);
   char *tgtaddr = grpc_sockaddr_to_uri(addr);
-  grpc_error *final_error = grpc_error_set_int(
+  grpc_error_set_int(
       grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING(
                              "Failed to prepare server socket", &error, 1),
                          GRPC_ERROR_STR_TARGET_ADDRESS, tgtaddr),
@@ -261,7 +260,6 @@ failure:
 
 static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx,
                                                      grpc_tcp_listener *sp) {
-  int notify = 0;
   sp->shutting_down = 0;
   GPR_ASSERT(sp->server->active_ports > 0);
   if (0 == --sp->server->active_ports) {
@@ -375,7 +373,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
       int peer_name_len = (int)peer_name.len;
       err =
           getpeername(sock, (struct sockaddr *)peer_name.addr, &peer_name_len);
-      peer_name.len = peer_name_len;
+      peer_name.len = (size_t)peer_name_len;
       if (!err) {
         peer_name_string = grpc_sockaddr_to_uri(&peer_name);
       } else {
@@ -498,7 +496,7 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
       if (0 == getsockname(sp->socket->socket,
                            (struct sockaddr *)sockname_temp.addr,
                            &sockname_temp_len)) {
-        sockname_temp.len = sockname_temp_len;
+        sockname_temp.len = (size_t)sockname_temp_len;
         *port = grpc_sockaddr_get_port(&sockname_temp);
         if (*port > 0) {
           allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
index e886cc59a02897a8dcd2f99b822fea24b017ff9c..5e75856c7a456b1c37e31436614a581b341041cb 100644
--- a/src/core/lib/security/transport/security_handshaker.c
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -42,6 +42,7 @@
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/security/transport/tsi_error.h"
@@ -437,6 +438,45 @@ static grpc_handshaker *fail_handshaker_create() {
   return h;
 }
 
+//
+// handshaker factories
+//
+
+static void client_handshaker_factory_add_handshakers(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
+    const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
+  grpc_channel_security_connector *security_connector =
+      (grpc_channel_security_connector *)grpc_find_security_connector_in_args(
+          args);
+  grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
+                                                  handshake_mgr);
+}
+
+static void server_handshaker_factory_add_handshakers(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf,
+    const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
+  grpc_server_security_connector *security_connector =
+      (grpc_server_security_connector *)grpc_find_security_connector_in_args(
+          args);
+  grpc_server_security_connector_add_handshakers(exec_ctx, security_connector,
+                                                 handshake_mgr);
+}
+
+static void handshaker_factory_destroy(
+    grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {}
+
+static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = {
+    client_handshaker_factory_add_handshakers, handshaker_factory_destroy};
+
+static grpc_handshaker_factory client_handshaker_factory = {
+    &client_handshaker_factory_vtable};
+
+static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = {
+    server_handshaker_factory_add_handshakers, handshaker_factory_destroy};
+
+static grpc_handshaker_factory server_handshaker_factory = {
+    &server_handshaker_factory_vtable};
+
 //
 // exported functions
 //
@@ -452,3 +492,10 @@ grpc_handshaker *grpc_security_handshaker_create(
     return security_handshaker_create(exec_ctx, handshaker, connector);
   }
 }
+
+void grpc_security_register_handshaker_factories() {
+  grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT,
+                                   &client_handshaker_factory);
+  grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER,
+                                   &server_handshaker_factory);
+}
diff --git a/src/core/lib/security/transport/security_handshaker.h b/src/core/lib/security/transport/security_handshaker.h
index 5ddbf4b4513830a4b331cf2d82be34df4894ffda..0b9eda178fdfe8e6b50d1a37808089b283822419 100644
--- a/src/core/lib/security/transport/security_handshaker.h
+++ b/src/core/lib/security/transport/security_handshaker.h
@@ -43,4 +43,7 @@ grpc_handshaker *grpc_security_handshaker_create(
     grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
     grpc_security_connector *connector);
 
+/// Registers security handshaker factories.
+void grpc_security_register_handshaker_factories();
+
 #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index e20e60254787c3a2a73afe7455891eba1da29b11..f61bf1582e56728b22f4998f31fa088e92a7d458 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -44,6 +44,7 @@
 #include "src/core/lib/channel/compress_filter.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/deadline_filter.h"
+#include "src/core/lib/channel/handshaker_registry.h"
 #include "src/core/lib/channel/http_client_filter.h"
 #include "src/core/lib/channel/http_server_filter.h"
 #include "src/core/lib/channel/message_size_filter.h"
@@ -204,6 +205,8 @@ void grpc_init(void) {
     grpc_executor_init();
     gpr_timers_global_init();
     grpc_cq_global_init();
+    grpc_handshaker_factory_registry_init();
+    grpc_security_init();
     for (i = 0; i < g_number_of_plugins; i++) {
       if (g_all_of_the_plugins[i].init != NULL) {
         g_all_of_the_plugins[i].init();
@@ -238,6 +241,7 @@ void grpc_shutdown(void) {
       }
     }
     grpc_mdctx_global_shutdown(&exec_ctx);
+    grpc_handshaker_factory_registry_shutdown(&exec_ctx);
   }
   gpr_mu_unlock(&g_init_mu);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
index b1bf57c10d197e8ef06cb377d0707cfeb1e683b0..3d1c528be043ea495160de3fe6a00a8107dcb25c 100644
--- a/src/core/lib/surface/init.h
+++ b/src/core/lib/surface/init.h
@@ -36,6 +36,7 @@
 
 void grpc_register_security_filters(void);
 void grpc_security_pre_init(void);
+void grpc_security_init(void);
 int grpc_is_initialized(void);
 
 #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
index 520a8aa84fa5f81f18fe774cf3c778b641d2e197..a44407d3bb4637559f77f8eddf216ac7ffb27289 100644
--- a/src/core/lib/surface/init_secure.c
+++ b/src/core/lib/surface/init_secure.c
@@ -41,6 +41,7 @@
 #include "src/core/lib/security/transport/auth_filters.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/security/transport/security_connector.h"
+#include "src/core/lib/security/transport/security_handshaker.h"
 #include "src/core/lib/surface/channel_init.h"
 #include "src/core/lib/tsi/transport_security_interface.h"
 
@@ -87,3 +88,5 @@ void grpc_register_security_filters(void) {
   grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
                                    maybe_prepend_server_auth_filter, NULL);
 }
+
+void grpc_security_init() { grpc_security_register_handshaker_factories(); }
diff --git a/src/core/lib/surface/init_unsecure.c b/src/core/lib/surface/init_unsecure.c
index f952739e0a9d7360fb6820287b3ce6062da5c3d4..dbc9223ae0d6bcc0e11d40543df1a41d57e4d6e7 100644
--- a/src/core/lib/surface/init_unsecure.c
+++ b/src/core/lib/surface/init_unsecure.c
@@ -36,3 +36,5 @@
 void grpc_security_pre_init(void) {}
 
 void grpc_register_security_filters(void) {}
+
+void grpc_security_init(void) {}
diff --git a/src/php/bin/generate_proto_php.sh b/src/php/bin/generate_proto_php.sh
index c558bc576981ac266bef54476ba7af931b8cf307..416fa9df97b246b3a95669ee7878b3991ad88f4a 100755
--- a/src/php/bin/generate_proto_php.sh
+++ b/src/php/bin/generate_proto_php.sh
@@ -39,10 +39,13 @@ protoc --proto_path=src/proto/math \
 
 # replace the Empty message with EmptyMessage
 # because Empty is a PHP reserved word
-sed -i 's/message Empty/message EmptyMessage/g' \
-    src/proto/grpc/testing/empty.proto
-sed -i 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \
-    src/proto/grpc/testing/test.proto
+output_file=$(mktemp)
+sed 's/message Empty/message EmptyMessage/g' \
+  src/proto/grpc/testing/empty.proto > $output_file
+mv $output_file ./src/proto/grpc/testing/empty.proto
+sed 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \
+  src/proto/grpc/testing/test.proto > $output_file
+mv $output_file ./src/proto/grpc/testing/test.proto
 
 protoc --proto_path=. \
        --php_out=src/php/tests/interop \
@@ -53,7 +56,10 @@ protoc --proto_path=. \
        src/proto/grpc/testing/test.proto
 
 # change it back
-sed -i 's/message EmptyMessage/message Empty/g' \
-    src/proto/grpc/testing/empty.proto
-sed -i 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \
-    src/proto/grpc/testing/test.proto
+sed 's/message EmptyMessage/message Empty/g' \
+  src/proto/grpc/testing/empty.proto > $output_file
+mv $output_file ./src/proto/grpc/testing/empty.proto
+sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \
+  src/proto/grpc/testing/test.proto > $output_file
+mv $output_file ./src/proto/grpc/testing/test.proto
+
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 3a49ea870813d55b06301cf0e7291f318be97a16..64b1137c2a454ba4bf2bbe782f0290b50787b200 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -478,6 +478,7 @@ PHP_METHOD(Call, startBatch) {
                                    true);
       add_property_zval(result, "status", recv_status);
       PHP_GRPC_DELREF(recv_status);
+      PHP_GRPC_FREE_STD_ZVAL(recv_status);
       break;
     case GRPC_OP_RECV_CLOSE_ON_SERVER:
       add_property_bool(result, "cancelled", cancelled);
@@ -501,6 +502,7 @@ cleanup:
     }
     if (ops[i].op == GRPC_OP_RECV_MESSAGE) {
       grpc_byte_buffer_destroy(message);
+      PHP_GRPC_FREE_STD_ZVAL(message_str);
     }
   }
   RETURN_DESTROY_ZVAL(result);
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index 3aafc3a19b667d761f188cb164a7b0f1c0907076..043817facd1c288f3c1bd6a2a461a6854ecfae89 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -111,9 +111,7 @@ PHP_METHOD(CallCredentials, createComposite) {
   grpc_call_credentials *creds =
       grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
                                              NULL);
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
@@ -155,9 +153,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
 
   grpc_call_credentials *creds =
     grpc_metadata_credentials_create_from_plugin(plugin, NULL);
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
@@ -211,6 +207,8 @@ void plugin_destroy_state(void *ptr) {
   plugin_state *state = (plugin_state *)ptr;
   efree(state->fci);
   efree(state->fci_cache);
+  PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
+  PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
   efree(state);
 }
 
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index a32c4a4ea24272059c8b05e21ed256185acdf229..36a8223b8806fe124737f3eac8c14f9e993ddc63 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -121,9 +121,7 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) {
  */
 PHP_METHOD(ChannelCredentials, createDefault) {
   grpc_channel_credentials *creds = grpc_google_default_credentials_create();
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
@@ -160,9 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
   grpc_channel_credentials *creds = grpc_ssl_credentials_create(
       pem_root_certs,
       pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
@@ -191,9 +187,7 @@ PHP_METHOD(ChannelCredentials, createComposite) {
   grpc_channel_credentials *creds =
       grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
                                                 NULL);
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h
index 1d7824113faf1be801726a73500e202607ca2669..72e982d6fc93aff101ae382dbad46b70f8c814cb 100644
--- a/src/php/ext/grpc/php7_wrapper.h
+++ b/src/php/ext/grpc/php7_wrapper.h
@@ -50,8 +50,13 @@
 
 #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup)
 #define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv)
+#define PHP_GRPC_FREE_STD_ZVAL(pzv)
 #define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv)
 
+#define RETURN_DESTROY_ZVAL(val) \
+  RETURN_ZVAL(val, false /* Don't execute copy constructor */, \
+              true /* Dealloc original before returning */)
+
 #define PHP_GRPC_WRAP_OBJECT_START(name) \
   typedef struct name { \
     zend_object std;
@@ -144,8 +149,15 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
 #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val)
 #define PHP_GRPC_MAKE_STD_ZVAL(pzv) \
   pzv = (zval *)emalloc(sizeof(zval));
+#define PHP_GRPC_FREE_STD_ZVAL(pzv) efree(pzv);
 #define PHP_GRPC_DELREF(zv)
 
+#define RETURN_DESTROY_ZVAL(val) \
+  RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \
+              true /* Dealloc original before returning */); \
+  efree(val); \
+  return
+
 #define PHP_GRPC_WRAP_OBJECT_START(name) \
   typedef struct name {
 #define PHP_GRPC_WRAP_OBJECT_END(name) \
diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h
index e57a06545e6c3f3cbc83055899ceb1ed1d5f80aa..13083b0bc71cb28aadda4bb76a63cd85e1b2a31d 100644
--- a/src/php/ext/grpc/php_grpc.h
+++ b/src/php/ext/grpc/php_grpc.h
@@ -61,10 +61,6 @@ extern zend_module_entry grpc_module_entry;
 
 #include "grpc/grpc.h"
 
-#define RETURN_DESTROY_ZVAL(val)                               \
-  RETURN_ZVAL(val, false /* Don't execute copy constructor */, \
-              true /* Dealloc original before returning */)
-
 /* These are all function declarations */
 /* Code that runs at module initialization */
 PHP_MINIT_FUNCTION(grpc);
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 1610c8ebb0982a6cdf6946289cd5e4b3a47a85d7..3e39fee246c4afe30f1e497ab57d9e2572568bac 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -113,9 +113,7 @@ PHP_METHOD(ServerCredentials, createSsl) {
   grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
       pem_root_certs, &pem_key_cert_pair, 1,
       GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL);
-  zval *creds_object;
-  PHP_GRPC_MAKE_STD_ZVAL(creds_object);
-  creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC);
+  zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 945231b47feb5e26352aefa8d31c3ee9f4c9d38b..7ada915aaddbd113f01f807c9a3437af4d7619eb 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -115,11 +115,9 @@ PHP_METHOD(Timeval, add) {
   }
   wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
   wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
-  zval *sum;
-  PHP_GRPC_MAKE_STD_ZVAL(sum);
-  sum =
-      grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
-                            TSRMLS_CC);
+  zval *sum =
+    grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
+                          TSRMLS_CC);
   RETURN_DESTROY_ZVAL(sum);
 }
 
@@ -141,11 +139,9 @@ PHP_METHOD(Timeval, subtract) {
   }
   wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
   wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
-  zval *diff;
-  PHP_GRPC_MAKE_STD_ZVAL(diff);
-  diff =
-      grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
-                            TSRMLS_CC);
+  zval *diff =
+    grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
+                          TSRMLS_CC);
   RETURN_DESTROY_ZVAL(diff);
 }
 
@@ -206,9 +202,7 @@ PHP_METHOD(Timeval, similar) {
  * @return Timeval The current time
  */
 PHP_METHOD(Timeval, now) {
-  zval *now;
-  PHP_GRPC_MAKE_STD_ZVAL(now);
-  now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
+  zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
   RETURN_DESTROY_ZVAL(now);
 }
 
@@ -217,13 +211,9 @@ PHP_METHOD(Timeval, now) {
  * @return Timeval Zero length time interval
  */
 PHP_METHOD(Timeval, zero) {
-  zval *grpc_php_timeval_zero;
-  PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_zero);
-  grpc_php_timeval_zero =
-      grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
-  RETURN_ZVAL(grpc_php_timeval_zero,
-              false, /* Copy original before returning? */
-              true /* Destroy original before returning */);
+  zval *grpc_php_timeval_zero =
+    grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
+  RETURN_DESTROY_ZVAL(grpc_php_timeval_zero);
 }
 
 /**
@@ -231,10 +221,8 @@ PHP_METHOD(Timeval, zero) {
  * @return Timeval Infinite future time value
  */
 PHP_METHOD(Timeval, infFuture) {
-  zval *grpc_php_timeval_inf_future;
-  PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_future);
-  grpc_php_timeval_inf_future =
-      grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
+  zval *grpc_php_timeval_inf_future =
+    grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
 }
 
@@ -243,10 +231,8 @@ PHP_METHOD(Timeval, infFuture) {
  * @return Timeval Infinite past time value
  */
 PHP_METHOD(Timeval, infPast) {
-  zval *grpc_php_timeval_inf_past;
-  PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_past);
-  grpc_php_timeval_inf_past =
-      grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
+  zval *grpc_php_timeval_inf_past =
+    grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
 }
 
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index aec60af094f1c5f429925e8c989a05b344d3c467..a9e77b9396acf948512b0ac487a6901bea12dcac 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -271,7 +271,7 @@ class BaseStub
      * @return ClientStreamingSurfaceActiveCall The active call object
      */
     public function _clientStreamRequest($method,
-                                         callable $deserialize,
+                                         $deserialize,
                                          array $metadata = [],
                                          array $options = [])
     {
@@ -307,7 +307,7 @@ class BaseStub
      */
     public function _serverStreamRequest($method,
                                          $argument,
-                                         callable $deserialize,
+                                         $deserialize,
                                          array $metadata = [],
                                          array $options = [])
     {
@@ -340,7 +340,7 @@ class BaseStub
      * @return BidiStreamingSurfaceActiveCall The active call object
      */
     public function _bidiRequest($method,
-                                 callable $deserialize,
+                                 $deserialize,
                                  array $metadata = [],
                                  array $options = [])
     {
diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto
index be387cf7869279cbd5d2de9d5f1690e8c1cc2098..529313cfb1ea5f38b0d9576838f2d1385acfe5f1 100644
--- a/src/proto/grpc/testing/control.proto
+++ b/src/proto/grpc/testing/control.proto
@@ -78,6 +78,14 @@ message SecurityParams {
   string server_host_override = 2;
 }
 
+message ChannelArg {
+  string name = 1;
+  oneof value {
+    string str_value = 2;
+    int32 int_value = 3;
+  }
+}
+
 message ClientConfig {
   // List of targets to connect to. At least one target needs to be specified.
   repeated string server_targets = 1;
@@ -103,6 +111,8 @@ message ClientConfig {
 
   // If we use an OTHER_CLIENT client_type, this string gives more detail
   string other_client_api = 15;
+
+  repeated ChannelArg channel_args = 16;
 }
 
 message ClientStatus { ClientStats stats = 1; }
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index d43f93b94fe1d9db7758a80e758c26bced727de9..e27e9e181d5158722efda4e616c77d9d92011fad 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -82,6 +82,8 @@ CORE_SOURCE_FILES = [
   'src/core/lib/channel/connected_channel.c',
   'src/core/lib/channel/deadline_filter.c',
   'src/core/lib/channel/handshaker.c',
+  'src/core/lib/channel/handshaker_factory.c',
+  'src/core/lib/channel/handshaker_registry.c',
   'src/core/lib/channel/http_client_filter.c',
   'src/core/lib/channel/http_server_filter.c',
   'src/core/lib/channel/message_size_filter.c',
diff --git a/src/python/grpcio_tests/tests/qps/benchmark_client.py b/src/python/grpcio_tests/tests/qps/benchmark_client.py
index 83b46c914e7f89d8d8966c29d573d69b6f310413..650e4756e7295169bcea373c5a68f19a15baa913 100644
--- a/src/python/grpcio_tests/tests/qps/benchmark_client.py
+++ b/src/python/grpcio_tests/tests/qps/benchmark_client.py
@@ -68,12 +68,8 @@ class BenchmarkClient:
     else:
       channel = grpc.insecure_channel(server)
 
-    connected_event = threading.Event()
-    def wait_for_ready(connectivity):
-      if connectivity == grpc.ChannelConnectivity.READY:
-        connected_event.set()
-    channel.subscribe(wait_for_ready, try_to_connect=True)
-    connected_event.wait()
+    # waits for the channel to be ready before we start sending messages
+    grpc.channel_ready_future(channel).result()
 
     if config.payload_config.WhichOneof('payload') == 'simple_params':
       self._generic = False
diff --git a/src/python/grpcio_tests/tests/stress/client.py b/src/python/grpcio_tests/tests/stress/client.py
index 390ea13021d1a37013230330c61b9dfd911a2e9a..b8116729b573ddc289392497850d8b3ce240789f 100644
--- a/src/python/grpcio_tests/tests/stress/client.py
+++ b/src/python/grpcio_tests/tests/stress/client.py
@@ -110,10 +110,13 @@ def _get_channel(target, args):
     channel_credentials = grpc.ssl_channel_credentials(
         root_certificates=root_certificates)
     options = (('grpc.ssl_target_name_override', args.server_host_override,),)
-    return grpc.secure_channel(
-        target, channel_credentials, options=options)
+    channel = grpc.secure_channel(target, channel_credentials, options=options)
   else:
-    return grpc.insecure_channel(target)
+    channel = grpc.insecure_channel(target)
+
+  # waits for the channel to be ready before we start sending messages
+  grpc.channel_ready_future(channel).result()
+  return channel
 
 def run_test(args):
   test_cases = _parse_weighted_test_cases(args.test_cases)
diff --git a/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb
index fde328e4c5d2053cf3bc7f58683bb543098991bf..7d1072e512c51701b7793a614d05a0ea43af9031 100644
--- a/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb
+++ b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb
@@ -54,6 +54,10 @@ module Grpc
         rpc :EmptyCall, Empty, Empty
         # One request followed by one response.
         rpc :UnaryCall, SimpleRequest, SimpleResponse
+        # One request followed by one response. Response has cache control
+        # headers set such that a caching HTTP proxy (such as GFE) can
+        # satisfy subsequent requests.
+        rpc :CacheableUnaryCall, SimpleRequest, SimpleResponse
         # One request followed by a sequence of responses (streamed download).
         # The server returns the payload with client desired type and sizes.
         rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse)
@@ -69,6 +73,9 @@ module Grpc
         # stream of responses are returned to the client when the server starts with
         # first request.
         rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse)
+        # The test server will not implement this method. It will be used
+        # to test the behavior when clients call unimplemented methods.
+        rpc :UnimplementedCall, Empty, Empty
       end
 
       Stub = Service.rpc_stub_class
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index f101f9d89ef054ffa0bb1b3d60b5de29a3941075..9c4ee9c6f2bb4b0ad3499951aa87fd87c734b666 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -158,14 +158,26 @@ def create_stub(opts)
 
     GRPC.logger.info("... connecting securely to #{address}")
     stub_opts[:channel_args].merge!(compression_channel_args)
-    Grpc::Testing::TestService::Stub.new(address, creds, **stub_opts)
+    if opts.test_case == "unimplemented_service"
+      Grpc::Testing::UnimplementedService::Stub.new(address, creds, **stub_opts)
+    else
+      Grpc::Testing::TestService::Stub.new(address, creds, **stub_opts)
+    end
   else
     GRPC.logger.info("... connecting insecurely to #{address}")
-    Grpc::Testing::TestService::Stub.new(
-      address,
-      :this_channel_is_insecure,
-      channel_args: compression_channel_args
-    )
+    if opts.test_case == "unimplemented_service"
+      Grpc::Testing::UnimplementedService::Stub.new(
+        address,
+        :this_channel_is_insecure,
+        channel_args: compression_channel_args
+      )
+    else
+      Grpc::Testing::TestService::Stub.new(
+        address,
+        :this_channel_is_insecure,
+        channel_args: compression_channel_args
+      )
+    end
   end
 end
 
@@ -502,6 +514,153 @@ class NamedTests
     op.wait
   end
 
+  def unimplemented_method
+    begin
+      resp = @stub.unimplemented_call(Empty.new)
+    rescue GRPC::Unimplemented => e
+      return
+    rescue Exception => e
+      fail AssertionError, "Expected BadStatus. Received: #{e.inspect}"
+    end
+    fail AssertionError, "GRPC::Unimplemented should have been raised. Was not."
+  end
+
+  def unimplemented_service
+    begin
+      resp = @stub.unimplemented_call(Empty.new)
+    rescue GRPC::Unimplemented => e
+      return
+    rescue Exception => e
+      fail AssertionError, "Expected BadStatus. Received: #{e.inspect}"
+    end
+    fail AssertionError, "GRPC::Unimplemented should have been raised. Was not."
+  end
+
+  def status_code_and_message
+
+    # Function wide constants.
+    message = "test status method"
+    code = GRPC::Core::StatusCodes::UNKNOWN
+
+    # Testing with UnaryCall.
+    payload = Payload.new(type: :COMPRESSABLE, body: nulls(1))
+    echo_status = EchoStatus.new(code: code, message: message)
+    req = SimpleRequest.new(response_type: :COMPRESSABLE,
+			    response_size: 1,
+			    payload: payload,
+			    response_status: echo_status)
+    seen_correct_exception = false
+    begin
+      resp = @stub.unary_call(req)
+    rescue GRPC::Unknown => e
+      if e.details != message
+	      fail AssertionError,
+	        "Expected message #{message}. Received: #{e.details}"
+      end
+      seen_correct_exception = true
+    rescue Exception => e
+      fail AssertionError, "Expected BadStatus. Received: #{e.inspect}"
+    end
+
+    if not seen_correct_exception
+      fail AssertionError, "Did not see expected status from UnaryCall"
+    end
+
+    # testing with FullDuplex
+    req_cls, p_cls = StreamingOutputCallRequest, ResponseParameters
+    duplex_req = req_cls.new(payload: Payload.new(body: nulls(1)),
+                  response_type: :COMPRESSABLE,
+                  response_parameters: [p_cls.new(size: 1)],
+                  response_status: echo_status)
+    seen_correct_exception = false
+    begin
+      resp = @stub.full_duplex_call([duplex_req])
+      resp.each { |r| }
+    rescue GRPC::Unknown => e
+      if e.details != message
+        fail AssertionError,
+          "Expected message #{message}. Received: #{e.details}"
+      end
+      seen_correct_exception = true
+    rescue Exception => e
+      fail AssertionError, "Expected BadStatus. Received: #{e.inspect}"
+    end
+
+    if not seen_correct_exception
+      fail AssertionError, "Did not see expected status from FullDuplexCall"
+    end
+
+  end
+
+
+  def custom_metadata
+
+    # Function wide constants
+    req_size, wanted_response_size = 271_828, 314_159
+    initial_metadata_key = "x-grpc-test-echo-initial"
+    initial_metadata_value = "test_initial_metadata_value"
+    trailing_metadata_key = "x-grpc-test-echo-trailing-bin"
+    trailing_metadata_value = "\x0a\x0b\x0a\x0b\x0a\x0b"
+
+    metadata = {
+      initial_metadata_key => initial_metadata_value,
+      trailing_metadata_key => trailing_metadata_value
+    }
+
+    # Testing with UnaryCall
+    payload = Payload.new(type: :COMPRESSABLE, body: nulls(req_size))
+    req = SimpleRequest.new(response_type: :COMPRESSABLE,
+			    response_size: wanted_response_size,
+			    payload: payload)
+
+    op = @stub.unary_call(req, metadata: metadata, return_op: true)
+    op.execute
+    if not op.metadata.has_key?(initial_metadata_key)
+      fail AssertionError, "Expected initial metadata. None received"
+    elsif op.metadata[initial_metadata_key] != metadata[initial_metadata_key]
+      fail AssertionError, 
+             "Expected initial metadata: #{metadata[initial_metadata_key]}. "\
+             "Received: #{op.metadata[initial_metadata_key]}"
+    end
+    if not op.trailing_metadata.has_key?(trailing_metadata_key)
+      fail AssertionError, "Expected trailing metadata. None received"
+    elsif op.trailing_metadata[trailing_metadata_key] !=
+          metadata[trailing_metadata_key]
+      fail AssertionError, 
+            "Expected trailing metadata: #{metadata[trailing_metadata_key]}. "\
+            "Received: #{op.trailing_metadata[trailing_metadata_key]}"
+    end
+
+    # Testing with FullDuplex
+    req_cls, p_cls = StreamingOutputCallRequest, ResponseParameters
+    duplex_req = req_cls.new(payload: Payload.new(body: nulls(req_size)),
+                  response_type: :COMPRESSABLE,
+                  response_parameters: [p_cls.new(size: wanted_response_size)])
+
+    duplex_op = @stub.full_duplex_call([duplex_req], metadata: metadata,
+                                        return_op: true)
+    resp = duplex_op.execute
+    resp.each { |r| } # ensures that the server sends trailing data
+    duplex_op.wait
+    if not duplex_op.metadata.has_key?(initial_metadata_key)
+      fail AssertionError, "Expected initial metadata. None received"
+    elsif duplex_op.metadata[initial_metadata_key] !=
+          metadata[initial_metadata_key]
+      fail AssertionError,
+             "Expected initial metadata: #{metadata[initial_metadata_key]}. "\
+             "Received: #{duplex_op.metadata[initial_metadata_key]}"
+    end
+    if not duplex_op.trailing_metadata[trailing_metadata_key]
+      fail AssertionError, "Expected trailing metadata. None received"
+    elsif duplex_op.trailing_metadata[trailing_metadata_key] !=
+          metadata[trailing_metadata_key]
+      fail AssertionError, 
+          "Expected trailing metadata: #{metadata[trailing_metadata_key]}. "\
+          "Received: #{duplex_op.trailing_metadata[trailing_metadata_key]}"
+    end
+
+  end
+
   def all
     all_methods = NamedTests.instance_methods(false).map(&:to_s)
     all_methods.each do |m|
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index c3c636c6af7db733bd1ec7e298735553ce7b8b38..028c1b8c32879bacb585e7e62605fb72b8e58940 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -84,7 +84,13 @@
   set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library")
 
   if (MSVC)
-    add_definitions( -D_WIN32_WINNT=0x600 )
+    add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
+    # needed to compile boringssl
+    add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027)
+    # needed to compile protobuf
+    add_definitions(/wd4065 /wd4506)
+    # TODO(jtattermusch): revisit C4267 occurrences throughout the code
+    add_definitions(/wd4267)
   endif()
 
   if (gRPC_USE_PROTO_LITE)
@@ -188,14 +194,19 @@
   endif()
 
   % for lib in libs:
-  % if lib.build in ["all", "protoc", "tool"]:
+  % if lib.build in ["all", "protoc", "tool"] and lib.language in ['c', 'c++']:
+  ## TODO(jtattermusch): grpc++_reflection includes .proto files
+  ## which is not yet supported and thus fails the entire build.
+  ## Re-enable once fixed.
+  % if lib.name != 'grpc++_reflection':
     ${cc_library(lib)}
     ${cc_install(lib)}
   % endif
+  % endif
   % endfor
 
   % for tgt in targets:
-  % if tgt.build in ["all", "protoc", "tool"]:
+  % if tgt.build in ["all", "protoc", "tool"] and tgt.language in ['c', 'c++']:
   ${cc_binary(tgt)}
   ${cc_install(tgt)}
   % endif
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 109de33c31eca42d9929373a64537e4320d2e519..230f16c0c89c262a9428791f275101f227f603bf 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -182,12 +182,19 @@
   endif
   STRIP ?= strip -x
   else
+  ifeq ($(SYSTEM),MINGW32)
+  ifeq ($(origin AR), default)
+  AR = ar rcs
+  endif
+  STRIP ?= strip --strip-unneeded
+  else
   ifeq ($(origin AR), default)
   AR = ar rcs
   endif
   STRIP ?= strip
   endif
   endif
+  endif
   INSTALL ?= install
   RM ?= rm -f
   PKG_CONFIG ?= pkg-config
@@ -392,6 +399,7 @@
   Libs.private: $(PC_LIBS_PRIVATE)
 
   ifeq ($(SYSTEM),MINGW32)
+  EXECUTABLE_SUFFIX = .exe
   SHARED_EXT_CORE = dll
   SHARED_EXT_CPP = dll
   SHARED_EXT_CSHARP = dll
@@ -400,6 +408,7 @@
   SHARED_VERSION_CPP = -${settings.cpp_version.major}
   SHARED_VERSION_CSHARP = -${settings.csharp_version.major}
   else ifeq ($(SYSTEM),Darwin)
+  EXECUTABLE_SUFFIX = 
   SHARED_EXT_CORE = dylib
   SHARED_EXT_CPP = dylib
   SHARED_EXT_CSHARP = dylib
@@ -408,6 +417,7 @@
   SHARED_VERSION_CPP =
   SHARED_VERSION_CSHARP =
   else
+  EXECUTABLE_SUFFIX = 
   SHARED_EXT_CORE = so.$(CORE_VERSION)
   SHARED_EXT_CPP = so.$(CPP_VERSION)
   SHARED_EXT_CSHARP = so.$(CSHARP_VERSION)
@@ -1196,7 +1206,7 @@
   $(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, []))}
   	$(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 $<
+  	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
   endif
 
   % endfor
@@ -1293,7 +1303,7 @@
   % if not lib.get('external_deps', None):
   	$(E) "[INSTALL] Installing $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]})"
   	$(Q) $(INSTALL) -d $(prefix)/lib
-  	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]})
+  	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]})
   ifeq ($(SYSTEM),MINGW32)
   	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
   else ifneq ($(SYSTEM),Darwin)
@@ -1322,9 +1332,6 @@
   ${install_shared("csharp")}
 
   install-plugins: $(PROTOC_PLUGINS)
-  ifeq ($(SYSTEM),MINGW32)
-  	$(Q) false
-  else
   	$(E) "[INSTALL] Installing grpc protoc plugins"
   % for tgt in targets:
   % if tgt.build == 'protoc':
@@ -1332,7 +1339,6 @@
   	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/${tgt.name} $(prefix)/bin/${tgt.name}
   % endif
   % endfor
-  endif
 
   install-pkg-config_c: pc_c pc_c_unsecure
   	$(E) "[INSTALL] Installing C pkg-config files"
@@ -1514,7 +1520,7 @@
         link_libs = link_libs + ' -l' + dep
         lib_deps = lib_deps + ' $(LIBDIR)/$(CONFIG)/lib' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')'
         mingw_libs = mingw_libs + ' -l' + dep + '-imp'
-        mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')'
+        mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '$(SHARED_VERSION_' + lang_to_var[dep_lib.language] + ').$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')'
 
     security = lib.get('secure', 'check')
     if security == True:
@@ -1546,17 +1552,17 @@
   ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}): $(LIB${lib.name.upper()}_OBJS) ${mingw_lib_deps}
   	$(E) "[LD]      Linking $@"
   	$(Q) mkdir -p `dirname $@`
-  	$(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared ${lib.name}.def -Wl,--output-def=${out_mingbase}.def -Wl,--out-implib=${out_libbase}-dll.a -o ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${mingw_libs}
+  	$(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=${out_mingbase}.def -Wl,--out-implib=${out_libbase}-dll.a -o ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${mingw_libs}
   else
   ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}): $(LIB${lib.name.upper()}_OBJS) ${lib_deps}
   	$(E) "[LD]      Linking $@"
   	$(Q) mkdir -p `dirname $@`
   ifeq ($(SYSTEM),Darwin)
-  	$(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs}
+  	$(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs}
   else
   	$(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.core_version.major} -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs}
-  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major}
-  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so
+  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major}
+  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so
   endif
   endif
   % endif
diff --git a/templates/config.m4.template b/templates/config.m4.template
index 5847d456f51c89c941065e04344f86ce0a2f4469..f5f1d23088dadeaedff737fc148349a366a6d484 100644
--- a/templates/config.m4.template
+++ b/templates/config.m4.template
@@ -7,9 +7,9 @@
     dnl Write more examples of tests here...
 
     dnl # --with-grpc -> add include path
-    PHP_ADD_INCLUDE(../../grpc/include)
-    PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc)
-    PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include)
+    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
+    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
+    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
 
     LIBS="-lpthread $LIBS"
 
diff --git a/templates/package.json.template b/templates/package.json.template
index 81f39d27f518361064cc84642c857771b007758c..eb85c06590ef92116272f621dc6c442f27566f15 100644
--- a/templates/package.json.template
+++ b/templates/package.json.template
@@ -52,7 +52,7 @@
       "poisson-process": "^0.2.1"
     },
     "engines": {
-      "node": ">=0.12.0"
+      "node": ">=1.1.0"
     },
     "binary": {
       "module_name": "grpc_node",
diff --git a/templates/tools/doxygen/Doxyfile.include b/templates/tools/doxygen/Doxyfile.include
index a22f07f33fbf23013ce9f63b2afefe95bfe9429d..e26ae2b948ae19f4c0e8e0028fd94a5e242170d3 100644
--- a/templates/tools/doxygen/Doxyfile.include
+++ b/templates/tools/doxygen/Doxyfile.include
@@ -787,7 +787,7 @@ WARN_LOGFILE           =
 # Note: If this tag is empty the current directory is searched.
 
 INPUT                  = ${
-    ' \\\n'.join(
+    ' \\\n'.join(sorted(
         itertools.chain(
             itertools.chain.from_iterable(
     			      target.public_headers +
@@ -798,7 +798,7 @@ INPUT                  = ${
             glob.glob('doc/*.md'),
             glob.glob('doc/%s/*.md' % docpackage),
             [] if not internal else srcdoc)
-    )
+    ))
 }
 
 # This tag can be used to specify the character encoding of the source files
diff --git a/templates/vsprojects/grpc.sln.template b/templates/vsprojects/grpc.sln.template
index ded98383dad0e24bd97069d66fc69bef74fd4811..0b28e936be2514d26e5a00157c92eadaf7370e1b 100644
--- a/templates/vsprojects/grpc.sln.template
+++ b/templates/vsprojects/grpc.sln.template
@@ -2,6 +2,6 @@
 --- |
   <%namespace file="sln_defs.include" import="gen_solution"/>\
   <%
-  solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test', 'fuzzer'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++')]
+  solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test', 'fuzzer'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++') and not p.name in ['z', 'boringssl', 'grpc++_reflection']]
   %>\
   ${gen_solution(solution_projects, use_dlls='yes')}
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 77f0a9a0480fcbc5bf8af910a3bf3db24e415cd5..dfe952eb373e336c90cd6758ea78eb891d0399ff 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -27,8 +27,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
-
 cc_test(
     name = "alloc_test",
     srcs = ["alloc_test.c"],
diff --git a/test/core/util/memory_counters.h b/test/core/util/memory_counters.h
index f33281650147fc77d7ec64191dc819c705c906b9..b9b2b3adda5dcad3140d87640b557830013cd648 100644
--- a/test/core/util/memory_counters.h
+++ b/test/core/util/memory_counters.h
@@ -34,6 +34,8 @@
 #ifndef GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H
 #define GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H
 
+#include <stddef.h>
+
 struct grpc_memory_counters {
   size_t total_size_relative;
   size_t total_size_absolute;
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 8e385d100c16f37b770e120149e8a6401c64ff19..2ce3f2f7bd9e3e07215ae3c05a3d3f9e23699dbe 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -254,7 +254,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
 
     // Setup server
     ServerBuilder builder;
-    auto server_creds = GetServerCredentials(GetParam().credentials_type);
+    auto server_creds = GetCredentialsProvider()->GetServerCredentials(
+        GetParam().credentials_type);
     builder.AddListeningPort(server_address_.str(), server_creds);
     builder.RegisterService(&service_);
     cq_ = builder.AddCompletionQueue();
@@ -283,8 +284,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
 
   void ResetStub() {
     ChannelArguments args;
-    auto channel_creds =
-        GetChannelCredentials(GetParam().credentials_type, &args);
+    auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
+        GetParam().credentials_type, &args);
     std::shared_ptr<Channel> channel =
         CreateCustomChannel(server_address_.str(), channel_creds, args);
     stub_ = grpc::testing::EchoTestService::NewStub(channel);
@@ -892,8 +893,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) {
 
 TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
   ChannelArguments args;
-  auto channel_creds =
-      GetChannelCredentials(GetParam().credentials_type, &args);
+  auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
+      GetParam().credentials_type, &args);
   std::shared_ptr<Channel> channel =
       CreateCustomChannel(server_address_.str(), channel_creds, args);
   std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub;
@@ -1404,11 +1405,15 @@ std::vector<TestScenario> CreateTestScenarios(bool test_disable_blocking,
   std::vector<grpc::string> credentials_types;
   std::vector<grpc::string> messages;
 
-  credentials_types.push_back(kInsecureCredentialsType);
-  auto sec_list = GetSecureCredentialsTypeList();
+  if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType,
+                                                      nullptr) != nullptr) {
+    credentials_types.push_back(kInsecureCredentialsType);
+  }
+  auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList();
   for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) {
     credentials_types.push_back(*sec);
   }
+  GPR_ASSERT(!credentials_types.empty());
 
   messages.push_back("Hello");
   for (int sz = 1; sz < test_big_limit; sz *= 2) {
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 9bb892c694bbd809b97eb80e51627b91f2dbea60..1a1a94e87c74ffe43eaaad71cb7b71a83d80ea5f 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -242,7 +242,8 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
     // Setup server
     ServerBuilder builder;
     ConfigureServerBuilder(&builder);
-    auto server_creds = GetServerCredentials(GetParam().credentials_type);
+    auto server_creds = GetCredentialsProvider()->GetServerCredentials(
+        GetParam().credentials_type);
     if (GetParam().credentials_type != kInsecureCredentialsType) {
       server_creds->SetAuthMetadataProcessor(processor);
     }
@@ -270,8 +271,8 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
     }
     EXPECT_TRUE(is_server_started_);
     ChannelArguments args;
-    auto channel_creds =
-        GetChannelCredentials(GetParam().credentials_type, &args);
+    auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
+        GetParam().credentials_type, &args);
     if (!user_agent_prefix_.empty()) {
       args.SetUserAgentPrefix(user_agent_prefix_);
     }
@@ -1520,11 +1521,18 @@ std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
   std::vector<TestScenario> scenarios;
   std::vector<grpc::string> credentials_types;
   if (test_secure) {
-    credentials_types = GetSecureCredentialsTypeList();
+    credentials_types =
+        GetCredentialsProvider()->GetSecureCredentialsTypeList();
   }
   if (test_insecure) {
-    credentials_types.push_back(kInsecureCredentialsType);
+    // Only add 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);
+    }
   }
+  GPR_ASSERT(!credentials_types.empty());
   for (auto it = credentials_types.begin(); it != credentials_types.end();
        ++it) {
     scenarios.emplace_back(false, *it);
@@ -1541,7 +1549,7 @@ INSTANTIATE_TEST_CASE_P(End2end, End2endTest,
 
 INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, true,
-                                                                false)));
+                                                                true)));
 
 INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(true, true,
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index c58910abc3fb5a3e5827be04ee90b435ae02ea9c..3265554444b9af68986713abeb5287f0dc9744f5 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -49,6 +49,7 @@
 #include "test/cpp/util/test_config.h"
 
 DEFINE_bool(use_tls, false, "Whether to use tls.");
+DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
 DEFINE_int32(server_port, 0, "Server port.");
 DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index c171969e147d35665fe5dd95d14f38db8cb8019b..91564e5dcefbb71c1f50a9d6f6deb97715f5ff5a 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -50,8 +50,10 @@
 #include "src/cpp/client/secure_credentials.h"
 #include "test/core/security/oauth2_utils.h"
 #include "test/cpp/util/create_test_channel.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 DECLARE_bool(use_tls);
+DECLARE_string(custom_credentials_type);
 DECLARE_bool(use_test_ca);
 DECLARE_int32(server_port);
 DECLARE_string(server_host);
@@ -114,8 +116,12 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
     creds = AccessTokenCredentials(raw_token);
     GPR_ASSERT(creds);
   }
-  return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls,
-                           !FLAGS_use_test_ca, creds);
+  if (FLAGS_custom_credentials_type.empty()) {
+    return CreateTestChannel(host_port, FLAGS_server_host_override,
+                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
+  } else {
+    return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
+  }
 }
 
 }  // namespace testing
diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc
new file mode 100644
index 0000000000000000000000000000000000000000..38aee43b26a947b9ed39b9e071e3d8ba194b6973
--- /dev/null
+++ b/test/cpp/interop/http2_client.cc
@@ -0,0 +1,272 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <thread>
+
+#include <gflags/gflags.h>
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/transport/byte_stream.h"
+#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/test.grpc.pb.h"
+#include "test/cpp/interop/http2_client.h"
+
+#include "src/core/lib/support/string.h"
+#include "test/cpp/util/create_test_channel.h"
+#include "test/cpp/util/test_config.h"
+
+namespace grpc {
+namespace testing {
+
+namespace {
+const int kLargeRequestSize = 271828;
+const int kLargeResponseSize = 314159;
+}  // namespace
+
+Http2Client::ServiceStub::ServiceStub(std::shared_ptr<Channel> channel)
+    : channel_(channel) {
+  stub_ = TestService::NewStub(channel);
+}
+
+TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); }
+
+Http2Client::Http2Client(std::shared_ptr<Channel> channel)
+    : serviceStub_(channel), channel_(channel) {}
+
+bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) {
+  if (s.error_code() == expected_code) {
+    return true;
+  }
+
+  gpr_log(GPR_ERROR, "Error status code: %d (expected: %d), message: %s",
+          s.error_code(), expected_code, s.error_message().c_str());
+  abort();
+}
+
+bool Http2Client::DoRstAfterHeader() {
+  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header");
+
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+  Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::UNKNOWN);
+  GPR_ASSERT(!response.has_payload());  // no data should be received
+
+  gpr_log(GPR_DEBUG, "Done testing reset stream after header");
+  return true;
+}
+
+bool Http2Client::DoRstAfterData() {
+  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data");
+
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+  Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::UNKNOWN);
+  GPR_ASSERT(response.has_payload());  // data should be received
+
+  gpr_log(GPR_DEBUG, "Done testing reset stream after data");
+  return true;
+}
+
+bool Http2Client::DoRstDuringData() {
+  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data");
+
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+  Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::UNKNOWN);
+  GPR_ASSERT(!response.has_payload());  // no data should be received
+
+  gpr_log(GPR_DEBUG, "Done testing reset stream during data");
+  return true;
+}
+
+bool Http2Client::DoGoaway() {
+  gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway");
+
+  int numCalls = 2;
+  for (int i = 0; i < numCalls; i++) {
+    ClientContext context;
+    SimpleRequest request;
+    SimpleResponse response;
+    request.set_response_size(kLargeResponseSize);
+    grpc::string payload(kLargeRequestSize, '\0');
+    request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+    Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+    AssertStatusCode(s, grpc::StatusCode::OK);
+    GPR_ASSERT(response.payload().body() ==
+               grpc::string(kLargeResponseSize, '\0'));
+  }
+
+  gpr_log(GPR_DEBUG, "Done testing goaway");
+  return true;
+}
+
+bool Http2Client::DoPing() {
+  gpr_log(GPR_DEBUG, "Sending RPC and expecting ping");
+
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+  Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::OK);
+  GPR_ASSERT(response.payload().body() ==
+             grpc::string(kLargeResponseSize, '\0'));
+
+  gpr_log(GPR_DEBUG, "Done testing ping");
+  return true;
+}
+
+void Http2Client::MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel) {
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+
+  Status s =
+      TestService::NewStub(channel)->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::OK);
+  GPR_ASSERT(response.payload().body() ==
+             grpc::string(kLargeResponseSize, '\0'));
+}
+
+bool Http2Client::DoMaxStreams() {
+  gpr_log(GPR_DEBUG, "Testing max streams");
+
+  // Make an initial call on the channel to ensure the server's max streams
+  // setting is received
+  ClientContext context;
+  SimpleRequest request;
+  SimpleResponse response;
+  request.set_response_size(kLargeResponseSize);
+  grpc::string payload(kLargeRequestSize, '\0');
+  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+  Status s =
+      TestService::NewStub(channel_)->UnaryCall(&context, request, &response);
+  AssertStatusCode(s, grpc::StatusCode::OK);
+  GPR_ASSERT(response.payload().body() ==
+             grpc::string(kLargeResponseSize, '\0'));
+
+  std::vector<std::thread> test_threads;
+
+  for (int i = 0; i < 10; i++) {
+    test_threads.emplace_back(
+        std::thread(&Http2Client::MaxStreamsWorker, this, channel_));
+  }
+
+  for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
+    it->join();
+  }
+
+  gpr_log(GPR_DEBUG, "Done testing max streams");
+  return true;
+}
+
+}  // namespace testing
+}  // namespace grpc
+
+DEFINE_int32(server_port, 0, "Server port.");
+DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
+DEFINE_string(test_case, "rst_after_header",
+              "Configure different test cases. Valid options are:\n\n"
+              "goaway\n"
+              "max_streams\n"
+              "ping\n"
+              "rst_after_data\n"
+              "rst_after_header\n"
+              "rst_during_data\n");
+
+int main(int argc, char** argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+  GPR_ASSERT(FLAGS_server_port);
+  const int host_port_buf_size = 1024;
+  char host_port[host_port_buf_size];
+  snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
+           FLAGS_server_port);
+  grpc::testing::Http2Client client(grpc::CreateTestChannel(host_port, false));
+  gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str());
+  int ret = 0;
+  if (FLAGS_test_case == "rst_after_header") {
+    client.DoRstAfterHeader();
+  } else if (FLAGS_test_case == "rst_after_data") {
+    client.DoRstAfterData();
+  } else if (FLAGS_test_case == "rst_during_data") {
+    client.DoRstDuringData();
+  } else if (FLAGS_test_case == "goaway") {
+    client.DoGoaway();
+  } else if (FLAGS_test_case == "ping") {
+    client.DoPing();
+  } else if (FLAGS_test_case == "max_streams") {
+    client.DoMaxStreams();
+  } else {
+    const char* testcases[] = {
+        "goaway",         "max_streams",      "ping",
+        "rst_after_data", "rst_after_header", "rst_during_data"};
+    char* joined_testcases =
+        gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL);
+
+    gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
+            FLAGS_test_case.c_str(), joined_testcases);
+    gpr_free(joined_testcases);
+    ret = 1;
+  }
+
+  return ret;
+}
diff --git a/test/cpp/interop/http2_client.h b/test/cpp/interop/http2_client.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a315f5abbab8b38e4ebcacd56c205f2d9bdf55f
--- /dev/null
+++ b/test/cpp/interop/http2_client.h
@@ -0,0 +1,80 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H
+#define GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H
+
+#include <memory>
+
+#include <grpc++/channel.h>
+#include <grpc/grpc.h>
+#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/test.grpc.pb.h"
+
+namespace grpc {
+namespace testing {
+
+class Http2Client {
+ public:
+  explicit Http2Client(std::shared_ptr<Channel> channel);
+  ~Http2Client() {}
+
+  bool DoRstAfterHeader();
+  bool DoRstAfterData();
+  bool DoRstDuringData();
+  bool DoGoaway();
+  bool DoPing();
+  bool DoMaxStreams();
+
+ private:
+  class ServiceStub {
+   public:
+    ServiceStub(std::shared_ptr<Channel> channel);
+
+    TestService::Stub* Get();
+
+   private:
+    std::unique_ptr<TestService::Stub> stub_;
+    std::shared_ptr<Channel> channel_;
+  };
+
+  void MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel);
+  bool AssertStatusCode(const Status& s, StatusCode expected_code);
+  ServiceStub serviceStub_;
+  std::shared_ptr<Channel> channel_;
+};
+
+}  // namespace testing
+}  // namespace grpc
+
+#endif  // GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index 67456ce18bbb0ddc8b80268fe52f06545f888113..956840ba7090d5bc374dbc49f196e0fb480bb1a4 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -56,6 +56,7 @@
 #include "test/cpp/util/test_config.h"
 
 DEFINE_bool(use_tls, false, "Whether to use tls.");
+DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_int32(port, 0, "Server port.");
 DEFINE_int32(max_send_message_size, -1, "The maximum send message size.");
 
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index 8b0b511bcb89d62d4e5642266b8aaaa83bf9e6b2..d395f50fa59297f86d7154cead138e50a67945e4 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -39,23 +39,23 @@
 #include <grpc++/security/server_credentials.h>
 
 #include "src/core/lib/surface/call_test_only.h"
-#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 DECLARE_bool(use_tls);
+DECLARE_string(custom_credentials_type);
 
 namespace grpc {
 namespace testing {
 
 std::shared_ptr<ServerCredentials> CreateInteropServerCredentials() {
-  if (FLAGS_use_tls) {
-    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);
+  if (!FLAGS_custom_credentials_type.empty()) {
+    return GetCredentialsProvider()->GetServerCredentials(
+        FLAGS_custom_credentials_type);
+  } else if (FLAGS_use_tls) {
+    return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType);
   } else {
-    return InsecureServerCredentials();
+    return GetCredentialsProvider()->GetServerCredentials(
+        kInsecureCredentialsType);
   }
 }
 
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 97e658869fe1e9c787f8b8ffa4d056aa2e80e1e8..562522de779c34c530299048b913207861ded048 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -147,6 +147,7 @@ DEFINE_bool(do_not_abort_on_transient_failures, true,
 // Options from client.cc (for compatibility with interop test).
 // TODO(sreek): Consolidate overlapping options
 DEFINE_bool(use_tls, false, "Whether to use tls.");
+DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
 DEFINE_int32(server_port, 0, "Server port.");
 DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index fdd78ebb899d2626278e4263674a6acbb8f978f4..18f9778fc6f90444d9842dd5e19ab442de881b6b 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -409,6 +409,7 @@ class ClientImpl : public Client {
       // old compilers happy with using this in std::vector
       ChannelArguments args;
       args.SetInt("shard_to_ensure_no_subchannel_merges", shard);
+      set_channel_args(config, &args);
       channel_ = CreateTestChannel(
           target, config.security_params().server_host_override(),
           config.has_security_params(), !config.security_params().use_test_ca(),
@@ -423,6 +424,18 @@ class ClientImpl : public Client {
     StubType* get_stub() { return stub_.get(); }
 
    private:
+    void set_channel_args(const ClientConfig& config, ChannelArguments* args) {
+      for (auto channel_arg : config.channel_args()) {
+        if (channel_arg.value_case() == ChannelArg::kStrValue) {
+          args->SetString(channel_arg.name(), channel_arg.str_value());
+        } else if (channel_arg.value_case() == ChannelArg::kIntValue) {
+          args->SetInt(channel_arg.name(), channel_arg.int_value());
+        } else {
+          gpr_log(GPR_ERROR, "Empty channel arg value.");
+        }
+      }
+    }
+
     std::shared_ptr<Channel> channel_;
     std::unique_ptr<StubType> stub_;
   };
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
index da835b995abbbe26d8067df2590b00694821ee83..57ee5ef63cd1eacbb94db2b9cfa239c5426d4bf6 100644
--- a/test/cpp/qps/qps_json_driver.cc
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -212,6 +212,7 @@ static bool QpsDriver() {
             SearchOfferedLoad(FLAGS_initial_search_value,
                               FLAGS_targeted_cpu_load, scenario, &success);
         gpr_log(GPR_INFO, "targeted_offered_load %f", targeted_offered_load);
+        GetCpuLoad(scenario, targeted_offered_load, &success);
       } else {
         gpr_log(GPR_ERROR, "Unimplemented search param");
       }
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index fe8b5d54235b1bd2fe64c24e4bf63db290ec95a3..ad62e03490e359501e2fa1a1dab1662ba34f5391 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -35,11 +35,37 @@
 
 #include <grpc++/create_channel.h>
 #include <grpc++/security/credentials.h>
+#include <grpc/support/log.h>
 
-#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 namespace grpc {
 
+namespace {
+
+const char kProdTlsCredentialsType[] = "prod_ssl";
+
+class SslCredentialProvider : public testing::CredentialTypeProvider {
+ public:
+  std::shared_ptr<ChannelCredentials> GetChannelCredentials(
+      grpc::ChannelArguments* args) override {
+    return SslCredentials(SslCredentialsOptions());
+  }
+  std::shared_ptr<ServerCredentials> GetServerCredentials() override {
+    return nullptr;
+  }
+};
+
+gpr_once g_once_init_add_prod_ssl_provider = GPR_ONCE_INIT;
+// Register ssl with non-test roots type to the credentials provider.
+void AddProdSslType() {
+  testing::GetCredentialsProvider()->AddSecureType(
+      kProdTlsCredentialsType, std::unique_ptr<testing::CredentialTypeProvider>(
+                                   new SslCredentialProvider));
+}
+
+}  // namespace
+
 // When ssl is enabled, if server is empty, override_hostname is used to
 // create channel. Otherwise, connect to server and override hostname if
 // override_hostname is provided.
@@ -61,16 +87,22 @@ std::shared_ptr<Channel> CreateTestChannel(
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args) {
   ChannelArguments channel_args(args);
+  std::shared_ptr<ChannelCredentials> channel_creds;
   if (enable_ssl) {
-    const char* roots_certs = use_prod_roots ? "" : test_root_cert;
-    SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
-
-    std::shared_ptr<ChannelCredentials> channel_creds =
-        SslCredentials(ssl_opts);
-
-    if (!server.empty() && !override_hostname.empty()) {
-      channel_args.SetSslTargetNameOverride(override_hostname);
+    if (use_prod_roots) {
+      gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType);
+      channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
+          kProdTlsCredentialsType, &channel_args);
+      if (!server.empty() && !override_hostname.empty()) {
+        channel_args.SetSslTargetNameOverride(override_hostname);
+      }
+    } else {
+      // override_hostname is discarded as the provider handles it.
+      channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
+          testing::kTlsCredentialsType, &channel_args);
     }
+    GPR_ASSERT(channel_creds != nullptr);
+
     const grpc::string& connect_to =
         server.empty() ? override_hostname : server;
     if (creds.get()) {
@@ -103,4 +135,18 @@ std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
   return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false);
 }
 
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, const grpc::string& credential_type,
+    const std::shared_ptr<CallCredentials>& creds) {
+  ChannelArguments channel_args;
+  std::shared_ptr<ChannelCredentials> channel_creds =
+      testing::GetCredentialsProvider()->GetChannelCredentials(credential_type,
+                                                               &channel_args);
+  GPR_ASSERT(channel_creds != nullptr);
+  if (creds.get()) {
+    channel_creds = CompositeChannelCredentials(channel_creds, creds);
+  }
+  return CreateCustomChannel(server, channel_creds, channel_args);
+}
+
 }  // namespace grpc
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index 4ff666dc1bc43b48cf6eb75ca55e7684d86a0319..ce71a97edbbf6b08d3bd5beb024a5dd20230b132 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -59,6 +59,10 @@ std::shared_ptr<Channel> CreateTestChannel(
     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);
+
 }  // namespace grpc
 
 #endif  // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index 0456b9666710ceb0e4fb13ce1929d8653ef78cd9..909b02a7019fe426733f140fbb4b06c5c3ca9576 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -43,25 +43,9 @@
 #include "test/core/end2end/data/ssl_test_data.h"
 
 namespace grpc {
+namespace testing {
 namespace {
 
-using grpc::testing::CredentialTypeProvider;
-
-// Provide test credentials. Thread-safe.
-class CredentialsProvider {
- public:
-  virtual ~CredentialsProvider() {}
-
-  virtual void AddSecureType(
-      const grpc::string& type,
-      std::unique_ptr<CredentialTypeProvider> type_provider) = 0;
-  virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
-      const grpc::string& type, ChannelArguments* args) = 0;
-  virtual std::shared_ptr<ServerCredentials> GetServerCredentials(
-      const grpc::string& type) = 0;
-  virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0;
-};
-
 class DefaultCredentialsProvider : public CredentialsProvider {
  public:
   ~DefaultCredentialsProvider() override {}
@@ -145,37 +129,21 @@ class DefaultCredentialsProvider : public CredentialsProvider {
       added_secure_type_providers_;
 };
 
-gpr_once g_once_init_provider = GPR_ONCE_INIT;
 CredentialsProvider* g_provider = nullptr;
 
-void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; }
-
-CredentialsProvider* GetProvider() {
-  gpr_once_init(&g_once_init_provider, &CreateDefaultProvider);
-  return g_provider;
-}
-
 }  // namespace
 
-namespace testing {
-
-void AddSecureType(const grpc::string& type,
-                   std::unique_ptr<CredentialTypeProvider> type_provider) {
-  GetProvider()->AddSecureType(type, std::move(type_provider));
-}
-
-std::shared_ptr<ChannelCredentials> GetChannelCredentials(
-    const grpc::string& type, ChannelArguments* args) {
-  return GetProvider()->GetChannelCredentials(type, args);
-}
-
-std::shared_ptr<ServerCredentials> GetServerCredentials(
-    const grpc::string& type) {
-  return GetProvider()->GetServerCredentials(type);
+CredentialsProvider* GetCredentialsProvider() {
+  if (g_provider == nullptr) {
+    g_provider = new DefaultCredentialsProvider;
+  }
+  return g_provider;
 }
 
-std::vector<grpc::string> GetSecureCredentialsTypeList() {
-  return GetProvider()->GetSecureCredentialsTypeList();
+void SetCredentialsProvider(CredentialsProvider* provider) {
+  // For now, forbids overriding provider.
+  GPR_ASSERT(g_provider == nullptr);
+  g_provider = provider;
 }
 
 }  // namespace testing
diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h
index 1fb311e556e8c9ac6dc99b463a6a71fe56286244..0bc52ebe4dfa2d433ee14b6603ef33c4cedbe7d8 100644
--- a/test/cpp/util/test_credentials_provider.h
+++ b/test/cpp/util/test_credentials_provider.h
@@ -59,23 +59,39 @@ class CredentialTypeProvider {
   virtual std::shared_ptr<ServerCredentials> GetServerCredentials() = 0;
 };
 
-// Add a secure type in addition to the defaults above
-// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the
-// functions below.
-void AddSecureType(const grpc::string& type,
-                   std::unique_ptr<CredentialTypeProvider> type_provider);
-
-// Provide channel credentials according to the given type. Alter the channel
-// arguments if needed.
-std::shared_ptr<ChannelCredentials> GetChannelCredentials(
-    const grpc::string& type, ChannelArguments* args);
-
-// Provide server credentials according to the given type.
-std::shared_ptr<ServerCredentials> GetServerCredentials(
-    const grpc::string& type);
-
-// Provide a list of secure credentials type.
-std::vector<grpc::string> GetSecureCredentialsTypeList();
+// Provide test credentials. Thread-safe.
+class CredentialsProvider {
+ public:
+  virtual ~CredentialsProvider() {}
+
+  // Add a secure type in addition to the defaults. The default provider has
+  // (kInsecureCredentialsType, kTlsCredentialsType).
+  virtual void AddSecureType(
+      const grpc::string& type,
+      std::unique_ptr<CredentialTypeProvider> type_provider) = 0;
+
+  // Provide channel credentials according to the given type. Alter the channel
+  // arguments if needed. Return nullptr if type is not registered.
+  virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
+      const grpc::string& type, ChannelArguments* args) = 0;
+
+  // Provide server credentials according to the given type.
+  // Return nullptr if type is not registered.
+  virtual std::shared_ptr<ServerCredentials> GetServerCredentials(
+      const grpc::string& type) = 0;
+
+  // Provide a list of secure credentials type.
+  virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0;
+};
+
+// Get the current provider. Create a default one if not set.
+// Not thread-safe.
+CredentialsProvider* GetCredentialsProvider();
+
+// Set the global provider. Takes ownership. The previous set provider will be
+// destroyed.
+// Not thread-safe.
+void SetCredentialsProvider(CredentialsProvider* provider);
 
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/http2_test/http2_base_server.py b/test/http2_test/http2_base_server.py
index ee7719b1a80826db965874e194ba5ac66a94e394..8de028ceb1b85a90c7e563eaf05fdff6088891f5 100644
--- a/test/http2_test/http2_base_server.py
+++ b/test/http2_test/http2_base_server.py
@@ -73,7 +73,6 @@ class H2ProtocolBaseServer(twisted.internet.protocol.Protocol):
 
   def on_connection_lost(self, reason):
     logging.info('Disconnected %s' % reason)
-    twisted.internet.reactor.callFromThread(twisted.internet.reactor.stop)
 
   def dataReceived(self, data):
     try:
diff --git a/test/http2_test/http2_test_server.py b/test/http2_test/http2_test_server.py
index 44e36d34b64df73b184eefbc9d4c3e20f4efe045..abde3433ad22782ab1757c52650e6575f4e8d014 100644
--- a/test/http2_test/http2_test_server.py
+++ b/test/http2_test/http2_test_server.py
@@ -73,18 +73,32 @@ class H2Factory(twisted.internet.protocol.Factory):
     else:
       return t().get_base_server()
 
+def parse_arguments():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--base_port', type=int, default=8080,
+    help='base port to run the servers (default: 8080). One test server is '
+    'started on each incrementing port, beginning with base_port, in the '
+    'following order: goaway,max_streams,ping,rst_after_data,rst_after_header,'
+    'rst_during_data'
+    )
+  return parser.parse_args()
+
+def start_test_servers(base_port):
+  """ Start one server per test case on incrementing port numbers
+  beginning with base_port """
+  index = 0
+  for test_case in sorted(_TEST_CASE_MAPPING.keys()):
+    portnum = base_port + index
+    logging.warning('serving on port %d : %s'%(portnum, test_case))
+    endpoint = twisted.internet.endpoints.TCP4ServerEndpoint(
+      twisted.internet.reactor, portnum, backlog=128)
+    endpoint.listen(H2Factory(test_case))
+    index += 1
+
 if __name__ == '__main__':
   logging.basicConfig(
     format='%(levelname) -10s %(asctime)s %(module)s:%(lineno)s | %(message)s',
     level=logging.INFO)
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--test_case', choices=sorted(_TEST_CASE_MAPPING.keys()),
-    help='test case to run', required=True)
-  parser.add_argument('--port', type=int, default=8080,
-    help='port to run the server (default: 8080)')
-  args = parser.parse_args()
-  logging.info('Running test case %s on port %d' % (args.test_case, args.port))
-  endpoint = twisted.internet.endpoints.TCP4ServerEndpoint(
-    twisted.internet.reactor, args.port, backlog=128)
-  endpoint.listen(H2Factory(args.test_case))
+  args = parse_arguments()
+  start_test_servers(args.base_port)
   twisted.internet.reactor.run()
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 13f440441bcceb60591858ee73ffa8277149cec3..fa9b7057c576c4d0a82fb20e85a726d12228a378 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -760,7 +760,35 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc++/alarm.h \
+INPUT                  = doc/PROTOCOL-HTTP2.md \
+doc/PROTOCOL-WEB.md \
+doc/binary-logging.md \
+doc/c-style-guide.md \
+doc/command_line_tool.md \
+doc/compression.md \
+doc/compression_cookbook.md \
+doc/connection-backoff-interop-test-description.md \
+doc/connection-backoff.md \
+doc/connectivity-semantics-and-api.md \
+doc/cpp-style-guide.md \
+doc/cpp/pending_api_cleanups.md \
+doc/cpp/perf_notes.md \
+doc/environment_variables.md \
+doc/epoll-polling-engine.md \
+doc/fail_fast.md \
+doc/g_stands_for.md \
+doc/health-checking.md \
+doc/http-grpc-status-mapping.md \
+doc/interop-test-descriptions.md \
+doc/load-balancing.md \
+doc/naming.md \
+doc/negative-http2-interop-test-descriptions.md \
+doc/server-reflection.md \
+doc/server_reflection_tutorial.md \
+doc/statuscodes.md \
+doc/stress_test_framework.md \
+doc/wait-for-ready.md \
+include/grpc++/alarm.h \
 include/grpc++/channel.h \
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
@@ -771,7 +799,35 @@ include/grpc++/generic/generic_stub.h \
 include/grpc++/grpc++.h \
 include/grpc++/impl/call.h \
 include/grpc++/impl/client_unary_call.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.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/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/status.h \
+include/grpc++/impl/codegen/status_code_enum.h \
+include/grpc++/impl/codegen/status_helper.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 \
 include/grpc++/impl/grpc_library.h \
 include/grpc++/impl/method_handler_impl.h \
 include/grpc++/impl/rpc_method.h \
@@ -802,81 +858,24 @@ 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 \
-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/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/status.h \
-include/grpc++/impl/codegen/status_code_enum.h \
-include/grpc++/impl/codegen/status_helper.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 \
-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/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/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/gpr_types.h \
+include/grpc/impl/codegen/grpc_types.h \
 include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/propagation_bits.h \
 include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/status.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 \
-doc/fail_fast.md \
-doc/g_stands_for.md \
-doc/wait-for-ready.md \
-doc/binary-logging.md \
-doc/compression.md \
-doc/c-style-guide.md \
-doc/PROTOCOL-WEB.md \
-doc/cpp-style-guide.md \
-doc/server_reflection_tutorial.md \
-doc/server-reflection.md \
-doc/interop-test-descriptions.md \
-doc/PROTOCOL-HTTP2.md \
-doc/compression_cookbook.md \
-doc/connection-backoff.md \
-doc/epoll-polling-engine.md \
-doc/connectivity-semantics-and-api.md \
-doc/load-balancing.md \
-doc/environment_variables.md \
-doc/naming.md \
-doc/stress_test_framework.md \
-doc/http-grpc-status-mapping.md \
-doc/health-checking.md \
-doc/connection-backoff-interop-test-description.md \
-doc/negative-http2-interop-test-descriptions.md \
-doc/command_line_tool.md \
-doc/statuscodes.md \
-doc/cpp/perf_notes.md \
-doc/cpp/pending_api_cleanups.md
+include/grpc/impl/codegen/sync_windows.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 a86dfde17260f94db52447398fb88c91410bb33f..bca5652a463fcee4d18fc11e01a149d3f6a85ccc 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -760,7 +760,35 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc++/alarm.h \
+INPUT                  = doc/PROTOCOL-HTTP2.md \
+doc/PROTOCOL-WEB.md \
+doc/binary-logging.md \
+doc/c-style-guide.md \
+doc/command_line_tool.md \
+doc/compression.md \
+doc/compression_cookbook.md \
+doc/connection-backoff-interop-test-description.md \
+doc/connection-backoff.md \
+doc/connectivity-semantics-and-api.md \
+doc/cpp-style-guide.md \
+doc/cpp/pending_api_cleanups.md \
+doc/cpp/perf_notes.md \
+doc/environment_variables.md \
+doc/epoll-polling-engine.md \
+doc/fail_fast.md \
+doc/g_stands_for.md \
+doc/health-checking.md \
+doc/http-grpc-status-mapping.md \
+doc/interop-test-descriptions.md \
+doc/load-balancing.md \
+doc/naming.md \
+doc/negative-http2-interop-test-descriptions.md \
+doc/server-reflection.md \
+doc/server_reflection_tutorial.md \
+doc/statuscodes.md \
+doc/stress_test_framework.md \
+doc/wait-for-ready.md \
+include/grpc++/alarm.h \
 include/grpc++/channel.h \
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
@@ -771,7 +799,36 @@ include/grpc++/generic/generic_stub.h \
 include/grpc++/grpc++.h \
 include/grpc++/impl/call.h \
 include/grpc++/impl/client_unary_call.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.h \
 include/grpc++/impl/codegen/core_codegen.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/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/status.h \
+include/grpc++/impl/codegen/status_code_enum.h \
+include/grpc++/impl/codegen/status_helper.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 \
 include/grpc++/impl/grpc_library.h \
 include/grpc++/impl/method_handler_impl.h \
 include/grpc++/impl/rpc_method.h \
@@ -802,128 +859,70 @@ 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 \
-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/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/status.h \
-include/grpc++/impl/codegen/status_code_enum.h \
-include/grpc++/impl/codegen/status_helper.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 \
-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/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/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/gpr_types.h \
+include/grpc/impl/codegen/grpc_types.h \
 include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/propagation_bits.h \
 include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/status.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/core_codegen.h \
-src/cpp/client/secure_credentials.h \
-src/cpp/common/secure_auth_context.h \
-src/cpp/server/secure_server_credentials.h \
-src/cpp/client/create_channel_internal.h \
-src/cpp/common/channel_filter.h \
-src/cpp/server/dynamic_thread_pool.h \
-src/cpp/server/thread_pool_interface.h \
-src/cpp/thread_manager/thread_manager.h \
-src/cpp/client/insecure_credentials.cc \
-src/cpp/client/secure_credentials.cc \
-src/cpp/common/auth_property_iterator.cc \
-src/cpp/common/secure_auth_context.cc \
-src/cpp/common/secure_channel_arguments.cc \
-src/cpp/common/secure_create_auth_context.cc \
-src/cpp/server/insecure_server_credentials.cc \
-src/cpp/server/secure_server_credentials.cc \
+src/cpp/README.md \
 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/client/insecure_credentials.cc \
+src/cpp/client/secure_credentials.cc \
+src/cpp/client/secure_credentials.h \
+src/cpp/codegen/codegen_init.cc \
+src/cpp/common/auth_property_iterator.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/secure_auth_context.cc \
+src/cpp/common/secure_auth_context.h \
+src/cpp/common/secure_channel_arguments.cc \
+src/cpp/common/secure_create_auth_context.cc \
 src/cpp/common/version_cc.cc \
 src/cpp/server/async_generic_service.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/insecure_server_credentials.cc \
+src/cpp/server/secure_server_credentials.cc \
+src/cpp/server/secure_server_credentials.h \
 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 \
-src/cpp/codegen/codegen_init.cc \
-doc/fail_fast.md \
-doc/g_stands_for.md \
-doc/wait-for-ready.md \
-doc/binary-logging.md \
-doc/compression.md \
-doc/c-style-guide.md \
-doc/PROTOCOL-WEB.md \
-doc/cpp-style-guide.md \
-doc/server_reflection_tutorial.md \
-doc/server-reflection.md \
-doc/interop-test-descriptions.md \
-doc/PROTOCOL-HTTP2.md \
-doc/compression_cookbook.md \
-doc/connection-backoff.md \
-doc/epoll-polling-engine.md \
-doc/connectivity-semantics-and-api.md \
-doc/load-balancing.md \
-doc/environment_variables.md \
-doc/naming.md \
-doc/stress_test_framework.md \
-doc/http-grpc-status-mapping.md \
-doc/health-checking.md \
-doc/connection-backoff-interop-test-description.md \
-doc/negative-http2-interop-test-descriptions.md \
-doc/command_line_tool.md \
-doc/statuscodes.md \
-doc/cpp/perf_notes.md \
-doc/cpp/pending_api_cleanups.md \
-src/cpp/README.md
+src/cpp/util/time_cc.cc
 
 # 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.core b/tools/doxygen/Doxyfile.core
index ec4d6813e83d43386f1d8a8d9fb98326a70a901a..ccbfe3a4e66ccfffcacf1062f24989e1016e4574 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -760,36 +760,73 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc/byte_buffer.h \
+INPUT                  = doc/PROTOCOL-HTTP2.md \
+doc/PROTOCOL-WEB.md \
+doc/binary-logging.md \
+doc/c-style-guide.md \
+doc/command_line_tool.md \
+doc/compression.md \
+doc/compression_cookbook.md \
+doc/connection-backoff-interop-test-description.md \
+doc/connection-backoff.md \
+doc/connectivity-semantics-and-api.md \
+doc/core/pending_api_cleanups.md \
+doc/cpp-style-guide.md \
+doc/environment_variables.md \
+doc/epoll-polling-engine.md \
+doc/fail_fast.md \
+doc/g_stands_for.md \
+doc/health-checking.md \
+doc/http-grpc-status-mapping.md \
+doc/interop-test-descriptions.md \
+doc/load-balancing.md \
+doc/naming.md \
+doc/negative-http2-interop-test-descriptions.md \
+doc/server-reflection.md \
+doc/server_reflection_tutorial.md \
+doc/statuscodes.md \
+doc/stress_test_framework.md \
+doc/wait-for-ready.md \
+include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
+include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
+include/grpc/grpc_security.h \
 include/grpc/grpc_security_constants.h \
-include/grpc/slice.h \
-include/grpc/slice_buffer.h \
-include/grpc/status.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/status.h \
 include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_windows.h \
 include/grpc/impl/codegen/atm_windows.h \
-include/grpc/impl/codegen/gpr_slice.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/gpr_types.h \
+include/grpc/impl/codegen/gpr_types.h \
+include/grpc/impl/codegen/grpc_types.h \
+include/grpc/impl/codegen/port_platform.h \
 include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/propagation_bits.h \
+include/grpc/impl/codegen/slice.h \
 include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/status.h \
 include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
-include/grpc/grpc_security.h \
-include/grpc/census.h \
+include/grpc/impl/codegen/sync_windows.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 \
@@ -815,46 +852,7 @@ 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/slice.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 \
-doc/fail_fast.md \
-doc/g_stands_for.md \
-doc/wait-for-ready.md \
-doc/binary-logging.md \
-doc/compression.md \
-doc/c-style-guide.md \
-doc/PROTOCOL-WEB.md \
-doc/cpp-style-guide.md \
-doc/server_reflection_tutorial.md \
-doc/server-reflection.md \
-doc/interop-test-descriptions.md \
-doc/PROTOCOL-HTTP2.md \
-doc/compression_cookbook.md \
-doc/connection-backoff.md \
-doc/epoll-polling-engine.md \
-doc/connectivity-semantics-and-api.md \
-doc/load-balancing.md \
-doc/environment_variables.md \
-doc/naming.md \
-doc/stress_test_framework.md \
-doc/http-grpc-status-mapping.md \
-doc/health-checking.md \
-doc/connection-backoff-interop-test-description.md \
-doc/negative-http2-interop-test-descriptions.md \
-doc/command_line_tool.md \
-doc/statuscodes.md \
-doc/core/pending_api_cleanups.md
+include/grpc/support/useful.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.core.internal b/tools/doxygen/Doxyfile.core.internal
index 34e5304ce4eb08844bab4f648b5b64ddd1481fb5..fc8fac32f0dc2b7338959705d6de3eb71808f59a 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -760,491 +760,461 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include/grpc/byte_buffer.h \
+INPUT                  = doc/PROTOCOL-HTTP2.md \
+doc/PROTOCOL-WEB.md \
+doc/binary-logging.md \
+doc/c-style-guide.md \
+doc/command_line_tool.md \
+doc/compression.md \
+doc/compression_cookbook.md \
+doc/connection-backoff-interop-test-description.md \
+doc/connection-backoff.md \
+doc/connectivity-semantics-and-api.md \
+doc/core/pending_api_cleanups.md \
+doc/cpp-style-guide.md \
+doc/environment_variables.md \
+doc/epoll-polling-engine.md \
+doc/fail_fast.md \
+doc/g_stands_for.md \
+doc/health-checking.md \
+doc/http-grpc-status-mapping.md \
+doc/interop-test-descriptions.md \
+doc/load-balancing.md \
+doc/naming.md \
+doc/negative-http2-interop-test-descriptions.md \
+doc/server-reflection.md \
+doc/server_reflection_tutorial.md \
+doc/statuscodes.md \
+doc/stress_test_framework.md \
+doc/wait-for-ready.md \
+include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
+include/grpc/census.h \
 include/grpc/compression.h \
 include/grpc/grpc.h \
 include/grpc/grpc_posix.h \
+include/grpc/grpc_security.h \
 include/grpc/grpc_security_constants.h \
-include/grpc/slice.h \
-include/grpc/slice_buffer.h \
-include/grpc/status.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/status.h \
 include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm.h \
+include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_gcc_sync.h \
+include/grpc/impl/codegen/atm_windows.h \
 include/grpc/impl/codegen/atm_windows.h \
-include/grpc/impl/codegen/gpr_slice.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/gpr_types.h \
+include/grpc/impl/codegen/gpr_types.h \
+include/grpc/impl/codegen/grpc_types.h \
 include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/port_platform.h \
+include/grpc/impl/codegen/propagation_bits.h \
 include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/slice.h \
+include/grpc/impl/codegen/status.h \
 include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync.h \
+include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
+include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
-include/grpc/grpc_security.h \
-include/grpc/census.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/compress_filter.h \
-src/core/lib/channel/connected_channel.h \
-src/core/lib/channel/context.h \
-src/core/lib/channel/deadline_filter.h \
-src/core/lib/channel/handshaker.h \
-src/core/lib/channel/http_client_filter.h \
-src/core/lib/channel/http_server_filter.h \
-src/core/lib/channel/message_size_filter.h \
-src/core/lib/compression/algorithm_metadata.h \
-src/core/lib/compression/message_compress.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/ev_epoll_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/load_file.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_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/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_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_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/iomgr/workqueue.h \
-src/core/lib/iomgr/workqueue_uv.h \
-src/core/lib/iomgr/workqueue_windows.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/percent_encoding.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/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/transport/byte_stream.h \
-src/core/lib/transport/connectivity_state.h \
-src/core/lib/transport/mdstr_hash_table.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/timeout_encoding.h \
-src/core/lib/transport/transport.h \
-src/core/lib/transport/transport_impl.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_errors.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/status_conversion.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/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/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/b64.h \
-src/core/lib/security/util/json_util.h \
-src/core/lib/tsi/fake_transport_security.h \
-src/core/lib/tsi/ssl_transport_security.h \
-src/core/lib/tsi/ssl_types.h \
-src/core/lib/tsi/transport_security.h \
-src/core/lib/tsi/transport_security_interface.h \
-src/core/ext/transport/chttp2/server/chttp2_server.h \
+include/grpc/impl/codegen/sync_windows.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 \
+src/core/README.md \
+src/core/ext/README.md \
+src/core/ext/census/README.md \
+src/core/ext/census/aggregation.h \
+src/core/ext/census/base_resources.c \
+src/core/ext/census/base_resources.h \
+src/core/ext/census/census_interface.h \
+src/core/ext/census/census_rpc_stats.h \
+src/core/ext/census/context.c \
+src/core/ext/census/gen/README.md \
+src/core/ext/census/gen/census.pb.c \
+src/core/ext/census/gen/census.pb.h \
+src/core/ext/census/gen/trace_context.pb.c \
+src/core/ext/census/gen/trace_context.pb.h \
+src/core/ext/census/grpc_context.c \
+src/core/ext/census/grpc_filter.c \
+src/core/ext/census/grpc_filter.h \
+src/core/ext/census/grpc_plugin.c \
+src/core/ext/census/initialize.c \
+src/core/ext/census/mlog.c \
+src/core/ext/census/mlog.h \
+src/core/ext/census/operation.c \
+src/core/ext/census/placeholders.c \
+src/core/ext/census/resource.c \
+src/core/ext/census/resource.h \
+src/core/ext/census/rpc_metric_id.h \
+src/core/ext/census/trace_context.c \
+src/core/ext/census/trace_context.h \
+src/core/ext/census/tracing.c \
+src/core/ext/client_channel/README.md \
+src/core/ext/client_channel/channel_connectivity.c \
+src/core/ext/client_channel/client_channel.c \
 src/core/ext/client_channel/client_channel.h \
+src/core/ext/client_channel/client_channel_factory.c \
 src/core/ext/client_channel/client_channel_factory.h \
+src/core/ext/client_channel/client_channel_plugin.c \
+src/core/ext/client_channel/connector.c \
 src/core/ext/client_channel/connector.h \
+src/core/ext/client_channel/default_initial_connect_string.c \
+src/core/ext/client_channel/http_connect_handshaker.c \
 src/core/ext/client_channel/http_connect_handshaker.h \
+src/core/ext/client_channel/initial_connect_string.c \
 src/core/ext/client_channel/initial_connect_string.h \
+src/core/ext/client_channel/lb_policy.c \
 src/core/ext/client_channel/lb_policy.h \
+src/core/ext/client_channel/lb_policy_factory.c \
 src/core/ext/client_channel/lb_policy_factory.h \
+src/core/ext/client_channel/lb_policy_registry.c \
 src/core/ext/client_channel/lb_policy_registry.h \
+src/core/ext/client_channel/parse_address.c \
 src/core/ext/client_channel/parse_address.h \
+src/core/ext/client_channel/resolver.c \
 src/core/ext/client_channel/resolver.h \
+src/core/ext/client_channel/resolver_factory.c \
 src/core/ext/client_channel/resolver_factory.h \
+src/core/ext/client_channel/resolver_registry.c \
 src/core/ext/client_channel/resolver_registry.h \
+src/core/ext/client_channel/subchannel.c \
 src/core/ext/client_channel/subchannel.h \
+src/core/ext/client_channel/subchannel_index.c \
 src/core/ext/client_channel/subchannel_index.h \
+src/core/ext/client_channel/uri_parser.c \
 src/core/ext/client_channel/uri_parser.h \
-src/core/ext/transport/chttp2/client/chttp2_connector.h \
+src/core/ext/lb_policy/grpclb/grpclb.c \
 src/core/ext/lb_policy/grpclb/grpclb.h \
+src/core/ext/lb_policy/grpclb/load_balancer_api.c \
 src/core/ext/lb_policy/grpclb/load_balancer_api.h \
+src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \
-third_party/nanopb/pb.h \
-third_party/nanopb/pb_common.h \
-third_party/nanopb/pb_decode.h \
-third_party/nanopb/pb_encode.h \
+src/core/ext/lb_policy/pick_first/pick_first.c \
+src/core/ext/lb_policy/round_robin/round_robin.c \
+src/core/ext/load_reporting/load_reporting.c \
 src/core/ext/load_reporting/load_reporting.h \
+src/core/ext/load_reporting/load_reporting_filter.c \
 src/core/ext/load_reporting/load_reporting_filter.h \
-src/core/ext/census/aggregation.h \
-src/core/ext/census/base_resources.h \
-src/core/ext/census/census_interface.h \
-src/core/ext/census/census_rpc_stats.h \
-src/core/ext/census/gen/census.pb.h \
-src/core/ext/census/gen/trace_context.pb.h \
-src/core/ext/census/grpc_filter.h \
-src/core/ext/census/mlog.h \
-src/core/ext/census/resource.h \
-src/core/ext/census/rpc_metric_id.h \
-src/core/ext/census/trace_context.h \
-src/core/lib/surface/init.c \
+src/core/ext/resolver/README.md \
+src/core/ext/resolver/dns/native/README.md \
+src/core/ext/resolver/dns/native/dns_resolver.c \
+src/core/ext/resolver/sockaddr/README.md \
+src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
+src/core/ext/transport/README.md \
+src/core/ext/transport/chttp2/README.md \
+src/core/ext/transport/chttp2/alpn/alpn.c \
+src/core/ext/transport/chttp2/alpn/alpn.h \
+src/core/ext/transport/chttp2/client/chttp2_connector.c \
+src/core/ext/transport/chttp2/client/chttp2_connector.h \
+src/core/ext/transport/chttp2/client/insecure/README.md \
+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/chttp2/client/secure/README.md \
+src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
+src/core/ext/transport/chttp2/server/chttp2_server.c \
+src/core/ext/transport/chttp2/server/chttp2_server.h \
+src/core/ext/transport/chttp2/server/insecure/README.md \
+src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
+src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \
+src/core/ext/transport/chttp2/server/secure/README.md \
+src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \
+src/core/ext/transport/chttp2/transport/README.md \
+src/core/ext/transport/chttp2/transport/bin_decoder.c \
+src/core/ext/transport/chttp2/transport/bin_decoder.h \
+src/core/ext/transport/chttp2/transport/bin_encoder.c \
+src/core/ext/transport/chttp2/transport/bin_encoder.h \
+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/frame.h \
+src/core/ext/transport/chttp2/transport/frame_data.c \
+src/core/ext/transport/chttp2/transport/frame_data.h \
+src/core/ext/transport/chttp2/transport/frame_goaway.c \
+src/core/ext/transport/chttp2/transport/frame_goaway.h \
+src/core/ext/transport/chttp2/transport/frame_ping.c \
+src/core/ext/transport/chttp2/transport/frame_ping.h \
+src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+src/core/ext/transport/chttp2/transport/frame_rst_stream.h \
+src/core/ext/transport/chttp2/transport/frame_settings.c \
+src/core/ext/transport/chttp2/transport/frame_settings.h \
+src/core/ext/transport/chttp2/transport/frame_window_update.c \
+src/core/ext/transport/chttp2/transport/frame_window_update.h \
+src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+src/core/ext/transport/chttp2/transport/hpack_encoder.h \
+src/core/ext/transport/chttp2/transport/hpack_parser.c \
+src/core/ext/transport/chttp2/transport/hpack_parser.h \
+src/core/ext/transport/chttp2/transport/hpack_table.c \
+src/core/ext/transport/chttp2/transport/hpack_table.h \
+src/core/ext/transport/chttp2/transport/http2_errors.h \
+src/core/ext/transport/chttp2/transport/huffsyms.c \
+src/core/ext/transport/chttp2/transport/huffsyms.h \
+src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+src/core/ext/transport/chttp2/transport/incoming_metadata.h \
+src/core/ext/transport/chttp2/transport/internal.h \
+src/core/ext/transport/chttp2/transport/parsing.c \
+src/core/ext/transport/chttp2/transport/status_conversion.c \
+src/core/ext/transport/chttp2/transport/status_conversion.h \
+src/core/ext/transport/chttp2/transport/stream_lists.c \
+src/core/ext/transport/chttp2/transport/stream_map.c \
+src/core/ext/transport/chttp2/transport/stream_map.h \
+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/lib/README.md \
+src/core/lib/channel/README.md \
 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/compress_filter.c \
+src/core/lib/channel/compress_filter.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/deadline_filter.c \
+src/core/lib/channel/deadline_filter.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/channel/http_client_filter.c \
+src/core/lib/channel/http_client_filter.h \
 src/core/lib/channel/http_server_filter.c \
+src/core/lib/channel/http_server_filter.h \
 src/core/lib/channel/message_size_filter.c \
+src/core/lib/channel/message_size_filter.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/debug/trace.c \
+src/core/lib/debug/trace.h \
 src/core/lib/http/format_request.c \
+src/core/lib/http/format_request.h \
 src/core/lib/http/httpcli.c \
+src/core/lib/http/httpcli.h \
+src/core/lib/http/httpcli_security_connector.c \
 src/core/lib/http/parser.c \
+src/core/lib/http/parser.h \
+src/core/lib/iomgr/README.md \
 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/ev_epoll_linux.c \
+src/core/lib/iomgr/ev_epoll_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/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/load_file.c \
+src/core/lib/iomgr/load_file.h \
 src/core/lib/iomgr/network_status_tracker.c \
+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_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/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_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_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/iomgr/workqueue.h \
 src/core/lib/iomgr/workqueue_uv.c \
+src/core/lib/iomgr/workqueue_uv.h \
 src/core/lib/iomgr/workqueue_windows.c \
+src/core/lib/iomgr/workqueue_windows.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/slice/percent_encoding.c \
-src/core/lib/slice/slice.c \
-src/core/lib/slice/slice_buffer.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/event_string.c \
-src/core/lib/surface/lame_client.c \
-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/byte_stream.c \
-src/core/lib/transport/connectivity_state.c \
-src/core/lib/transport/mdstr_hash_table.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/timeout_encoding.c \
-src/core/lib/transport/transport.c \
-src/core/lib/transport/transport_op_string.c \
-src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.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/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/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/status_conversion.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/lib/http/httpcli_security_connector.c \
+src/core/lib/json/json_writer.h \
+src/core/lib/profiling/basic_timers.c \
+src/core/lib/profiling/stap_timers.c \
+src/core/lib/profiling/timers.h \
 src/core/lib/security/context/security_context.c \
+src/core/lib/security/context/security_context.h \
 src/core/lib/security/credentials/composite/composite_credentials.c \
+src/core/lib/security/credentials/composite/composite_credentials.h \
 src/core/lib/security/credentials/credentials.c \
+src/core/lib/security/credentials/credentials.h \
 src/core/lib/security/credentials/credentials_metadata.c \
 src/core/lib/security/credentials/fake/fake_credentials.c \
+src/core/lib/security/credentials/fake/fake_credentials.h \
 src/core/lib/security/credentials/google_default/credentials_generic.c \
 src/core/lib/security/credentials/google_default/google_default_credentials.c \
+src/core/lib/security/credentials/google_default/google_default_credentials.h \
 src/core/lib/security/credentials/iam/iam_credentials.c \
+src/core/lib/security/credentials/iam/iam_credentials.h \
 src/core/lib/security/credentials/jwt/json_token.c \
+src/core/lib/security/credentials/jwt/json_token.h \
 src/core/lib/security/credentials/jwt/jwt_credentials.c \
+src/core/lib/security/credentials/jwt/jwt_credentials.h \
 src/core/lib/security/credentials/jwt/jwt_verifier.c \
+src/core/lib/security/credentials/jwt/jwt_verifier.h \
 src/core/lib/security/credentials/oauth2/oauth2_credentials.c \
+src/core/lib/security/credentials/oauth2/oauth2_credentials.h \
 src/core/lib/security/credentials/plugin/plugin_credentials.c \
+src/core/lib/security/credentials/plugin/plugin_credentials.h \
 src/core/lib/security/credentials/ssl/ssl_credentials.c \
+src/core/lib/security/credentials/ssl/ssl_credentials.h \
+src/core/lib/security/transport/auth_filters.h \
 src/core/lib/security/transport/client_auth_filter.c \
 src/core/lib/security/transport/secure_endpoint.c \
+src/core/lib/security/transport/secure_endpoint.h \
 src/core/lib/security/transport/security_connector.c \
+src/core/lib/security/transport/security_connector.h \
 src/core/lib/security/transport/security_handshaker.c \
+src/core/lib/security/transport/security_handshaker.h \
 src/core/lib/security/transport/server_auth_filter.c \
 src/core/lib/security/transport/tsi_error.c \
+src/core/lib/security/transport/tsi_error.h \
 src/core/lib/security/util/b64.c \
+src/core/lib/security/util/b64.h \
 src/core/lib/security/util/json_util.c \
-src/core/lib/surface/init_secure.c \
-src/core/lib/tsi/fake_transport_security.c \
-src/core/lib/tsi/ssl_transport_security.c \
-src/core/lib/tsi/transport_security.c \
-src/core/ext/transport/chttp2/server/chttp2_server.c \
-src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
-src/core/ext/client_channel/channel_connectivity.c \
-src/core/ext/client_channel/client_channel.c \
-src/core/ext/client_channel/client_channel_factory.c \
-src/core/ext/client_channel/client_channel_plugin.c \
-src/core/ext/client_channel/connector.c \
-src/core/ext/client_channel/default_initial_connect_string.c \
-src/core/ext/client_channel/http_connect_handshaker.c \
-src/core/ext/client_channel/initial_connect_string.c \
-src/core/ext/client_channel/lb_policy.c \
-src/core/ext/client_channel/lb_policy_factory.c \
-src/core/ext/client_channel/lb_policy_registry.c \
-src/core/ext/client_channel/parse_address.c \
-src/core/ext/client_channel/resolver.c \
-src/core/ext/client_channel/resolver_factory.c \
-src/core/ext/client_channel/resolver_registry.c \
-src/core/ext/client_channel/subchannel.c \
-src/core/ext/client_channel/subchannel_index.c \
-src/core/ext/client_channel/uri_parser.c \
-src/core/ext/transport/chttp2/client/chttp2_connector.c \
-src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
-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/lb_policy/grpclb/grpclb.c \
-src/core/ext/lb_policy/grpclb/load_balancer_api.c \
-src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
-third_party/nanopb/pb_common.c \
-third_party/nanopb/pb_decode.c \
-third_party/nanopb/pb_encode.c \
-src/core/ext/lb_policy/pick_first/pick_first.c \
-src/core/ext/lb_policy/round_robin/round_robin.c \
-src/core/ext/resolver/dns/native/dns_resolver.c \
-src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
-src/core/ext/load_reporting/load_reporting.c \
-src/core/ext/load_reporting/load_reporting_filter.c \
-src/core/ext/census/base_resources.c \
-src/core/ext/census/context.c \
-src/core/ext/census/gen/census.pb.c \
-src/core/ext/census/gen/trace_context.pb.c \
-src/core/ext/census/grpc_context.c \
-src/core/ext/census/grpc_filter.c \
-src/core/ext/census/grpc_plugin.c \
-src/core/ext/census/initialize.c \
-src/core/ext/census/mlog.c \
-src/core/ext/census/operation.c \
-src/core/ext/census/placeholders.c \
-src/core/ext/census/resource.c \
-src/core/ext/census/trace_context.c \
-src/core/ext/census/tracing.c \
-src/core/plugin_registry/grpc_plugin_registry.c \
-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/slice.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 \
-src/core/lib/profiling/timers.h \
-src/core/lib/support/backoff.h \
-src/core/lib/support/block_annotate.h \
-src/core/lib/support/env.h \
-src/core/lib/support/mpscq.h \
-src/core/lib/support/murmur_hash.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/profiling/basic_timers.c \
-src/core/lib/profiling/stap_timers.c \
+src/core/lib/security/util/json_util.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_internal.h \
+src/core/lib/slice/slice_string_helpers.c \
+src/core/lib/slice/slice_string_helpers.h \
 src/core/lib/support/alloc.c \
 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 \
@@ -1256,77 +1226,109 @@ 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/mpscq.h \
 src/core/lib/support/murmur_hash.c \
+src/core/lib/support/murmur_hash.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 \
-doc/fail_fast.md \
-doc/g_stands_for.md \
-doc/wait-for-ready.md \
-doc/binary-logging.md \
-doc/compression.md \
-doc/c-style-guide.md \
-doc/PROTOCOL-WEB.md \
-doc/cpp-style-guide.md \
-doc/server_reflection_tutorial.md \
-doc/server-reflection.md \
-doc/interop-test-descriptions.md \
-doc/PROTOCOL-HTTP2.md \
-doc/compression_cookbook.md \
-doc/connection-backoff.md \
-doc/epoll-polling-engine.md \
-doc/connectivity-semantics-and-api.md \
-doc/load-balancing.md \
-doc/environment_variables.md \
-doc/naming.md \
-doc/stress_test_framework.md \
-doc/http-grpc-status-mapping.md \
-doc/health-checking.md \
-doc/connection-backoff-interop-test-description.md \
-doc/negative-http2-interop-test-descriptions.md \
-doc/command_line_tool.md \
-doc/statuscodes.md \
-doc/core/pending_api_cleanups.md \
-src/core/README.md \
-src/core/ext/README.md \
-src/core/ext/resolver/README.md \
-src/core/ext/resolver/dns/native/README.md \
-src/core/ext/resolver/sockaddr/README.md \
-src/core/ext/client_channel/README.md \
-src/core/ext/transport/README.md \
-src/core/ext/transport/chttp2/README.md \
-src/core/ext/transport/chttp2/client/insecure/README.md \
-src/core/ext/transport/chttp2/client/secure/README.md \
-src/core/ext/transport/chttp2/server/insecure/README.md \
-src/core/ext/transport/chttp2/server/secure/README.md \
-src/core/ext/transport/chttp2/transport/README.md \
-src/core/ext/census/README.md \
-src/core/ext/census/gen/README.md \
-src/core/lib/README.md \
-src/core/lib/iomgr/README.md \
-src/core/lib/tsi/README.md \
 src/core/lib/surface/README.md \
+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/event_string.c \
+src/core/lib/surface/event_string.h \
+src/core/lib/surface/init.c \
+src/core/lib/surface/init.h \
+src/core/lib/surface/init_secure.c \
+src/core/lib/surface/lame_client.c \
+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/version.c \
 src/core/lib/transport/README.md \
-src/core/lib/channel/README.md
+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/mdstr_hash_table.c \
+src/core/lib/transport/mdstr_hash_table.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/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/tsi/README.md \
+src/core/lib/tsi/fake_transport_security.c \
+src/core/lib/tsi/fake_transport_security.h \
+src/core/lib/tsi/ssl_transport_security.c \
+src/core/lib/tsi/ssl_transport_security.h \
+src/core/lib/tsi/ssl_types.h \
+src/core/lib/tsi/transport_security.c \
+src/core/lib/tsi/transport_security.h \
+src/core/lib/tsi/transport_security_interface.h \
+src/core/plugin_registry/grpc_plugin_registry.c \
+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
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/tools/run_tests/artifacts/build_artifact_node.bat b/tools/run_tests/artifacts/build_artifact_node.bat
index 2e0ecd21d0fe6e85164b85eb0a1c5152d921753c..59644c889656f87dff96ba7ff5c02ad7fa8bc7a3 100644
--- a/tools/run_tests/artifacts/build_artifact_node.bat
+++ b/tools/run_tests/artifacts/build_artifact_node.bat
@@ -27,7 +27,7 @@
 @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 7.0.0
+set node_versions=1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 7.0.0
 
 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
 
diff --git a/tools/run_tests/artifacts/build_artifact_node.sh b/tools/run_tests/artifacts/build_artifact_node.sh
index 1066ebde19c2c9be71fdae8758e82101b37be9d7..1deb33ba86bf9286cab1f0e498fe591fe18cf38b 100755
--- a/tools/run_tests/artifacts/build_artifact_node.sh
+++ b/tools/run_tests/artifacts/build_artifact_node.sh
@@ -42,7 +42,7 @@ mkdir -p artifacts
 
 npm update
 
-node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 7.0.0 )
+node_versions=( 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 7.0.0 )
 
 for version in ${node_versions[@]}
 do
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 67724db022e2eca7269769a5483323af46283c8d..84cca74ba495966d3c41f50a016213410384b71f 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -2772,6 +2772,23 @@
     "third_party": false, 
     "type": "target"
   }, 
+  {
+    "deps": [
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_config", 
+      "grpc++_test_util", 
+      "grpc_test_util", 
+      "http2_client_main"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "http2_client", 
+    "src": [], 
+    "third_party": false, 
+    "type": "target"
+  }, 
   {
     "deps": [
       "gpr", 
@@ -5388,6 +5405,33 @@
     "third_party": false, 
     "type": "lib"
   }, 
+  {
+    "deps": [
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_config", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [
+      "src/proto/grpc/testing/empty.grpc.pb.h", 
+      "src/proto/grpc/testing/empty.pb.h", 
+      "src/proto/grpc/testing/messages.grpc.pb.h", 
+      "src/proto/grpc/testing/messages.pb.h", 
+      "src/proto/grpc/testing/test.grpc.pb.h", 
+      "src/proto/grpc/testing/test.pb.h", 
+      "test/cpp/interop/http2_client.h"
+    ], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "http2_client_main", 
+    "src": [
+      "test/cpp/interop/http2_client.cc", 
+      "test/cpp/interop/http2_client.h"
+    ], 
+    "third_party": false, 
+    "type": "lib"
+  }, 
   {
     "deps": [
       "gpr", 
@@ -5447,6 +5491,7 @@
       "gpr", 
       "grpc", 
       "grpc++", 
+      "grpc++_test_util", 
       "grpc_test_util"
     ], 
     "headers": [
@@ -6683,6 +6728,8 @@
       "src/core/lib/channel/context.h", 
       "src/core/lib/channel/deadline_filter.h", 
       "src/core/lib/channel/handshaker.h", 
+      "src/core/lib/channel/handshaker_factory.h", 
+      "src/core/lib/channel/handshaker_registry.h", 
       "src/core/lib/channel/http_client_filter.h", 
       "src/core/lib/channel/http_server_filter.h", 
       "src/core/lib/channel/message_size_filter.h", 
@@ -6802,6 +6849,10 @@
       "src/core/lib/channel/deadline_filter.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/channel/http_client_filter.c", 
       "src/core/lib/channel/http_client_filter.h", 
       "src/core/lib/channel/http_server_filter.c", 
diff --git a/tools/run_tests/performance/bq_upload_result.py b/tools/run_tests/performance/bq_upload_result.py
index ddcf053ae5ec9a92aead775bc55a4c3332665faa..89d2a9b320fde3b83914593b5e025b1ca3be3a34 100755
--- a/tools/run_tests/performance/bq_upload_result.py
+++ b/tools/run_tests/performance/bq_upload_result.py
@@ -115,9 +115,11 @@ def _flatten_result_inplace(scenario_result):
   scenario_result['scenario']['clientConfig'] = json.dumps(scenario_result['scenario']['clientConfig'])
   scenario_result['scenario']['serverConfig'] = json.dumps(scenario_result['scenario']['serverConfig'])
   scenario_result['latencies'] = json.dumps(scenario_result['latencies'])
+  scenario_result['serverCpuStats'] = []
   for stats in scenario_result['serverStats']:
-    stats.pop('totalCpuTime', None)
-    stats.pop('idleCpuTime', None)
+    scenario_result['serverCpuStats'].append(dict())
+    scenario_result['serverCpuStats'][-1]['totalCpuTime'] = stats.pop('totalCpuTime', None)
+    scenario_result['serverCpuStats'][-1]['idleCpuTime'] = stats.pop('idleCpuTime', None)
   for stats in scenario_result['clientStats']:
     stats['latencies'] = json.dumps(stats['latencies'])
     stats.pop('requestResults', None)
@@ -125,7 +127,7 @@ def _flatten_result_inplace(scenario_result):
   scenario_result['clientSuccess'] = json.dumps(scenario_result['clientSuccess'])
   scenario_result['serverSuccess'] = json.dumps(scenario_result['serverSuccess'])
   scenario_result['requestResults'] = json.dumps(scenario_result.get('requestResults', []))
-  scenario_result['summary'].pop('serverCpuUsage', None)
+  scenario_result['serverCpuUsage'] = scenario_result['summary'].pop('serverCpuUsage', None)
   scenario_result['summary'].pop('successfulRequestsPerSecond', None)
   scenario_result['summary'].pop('failedRequestsPerSecond', None)
 
diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json
index 3285f212d7752380a218aa549571ec37a6ec77e2..8ec41c377c500cb4c19d166f81f6167693eeacd1 100644
--- a/tools/run_tests/performance/scenario_result_schema.json
+++ b/tools/run_tests/performance/scenario_result_schema.json
@@ -213,5 +213,27 @@
     "name": "requestResults",
     "type": "STRING",
     "mode": "NULLABLE"
+  },
+  {
+    "name": "serverCpuStats",
+    "type": "RECORD",
+    "mode": "REPEATED",
+    "fields": [
+      {
+        "name": "totalCpuTime",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      },
+      {
+        "name": "idleCpuTime",
+        "type": "INTEGER",
+        "mode": "NULLABLE"
+      }
+    ]
+  },
+  {
+    "name": "serverCpuUsage",
+    "type": "FLOAT",
+    "mode": "NULLABLE"
   }
 ]
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 981e38b813dec01b52432ca54d6ed02fefbaea53..56efac50ca0d23793468f18680b683c8c4c18704 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -169,6 +169,9 @@ class JavaLanguage:
   def client_cmd(self, args):
     return ['./run-test-client.sh'] + args
 
+  def client_cmd_http2interop(self, args):
+    return ['./run-http2-client.sh'] + args
+
   def cloud_to_prod_env(self):
     return {}
 
@@ -217,6 +220,33 @@ class GoLanguage:
   def __str__(self):
     return 'go'
 
+class Http2Server:
+  """Represents the HTTP/2 Interop Test server
+
+  This pretends to be a language in order to be built and run, but really it
+  isn't.
+  """
+  def __init__(self):
+    self.server_cwd = None
+    self.safename = str(self)
+
+  def server_cmd(self, args):
+    return ['python test/http2_test/http2_test_server.py']
+
+  def cloud_to_prod_env(self):
+    return {}
+
+  def global_env(self):
+    return {}
+
+  def unimplemented_test_cases(self):
+    return _TEST_CASES
+
+  def unimplemented_test_cases_server(self):
+    return _TEST_CASES
+
+  def __str__(self):
+    return 'http2'
 
 class Http2Client:
   """Represents the HTTP/2 Interop Test
@@ -350,10 +380,10 @@ class RubyLanguage:
     return {}
 
   def unimplemented_test_cases(self):
-    return _SKIP_ADVANCED + _SKIP_SERVER_COMPRESSION
+    return _SKIP_SERVER_COMPRESSION
 
   def unimplemented_test_cases_server(self):
-    return _SKIP_ADVANCED + _SKIP_COMPRESSION
+    return _SKIP_COMPRESSION
 
   def __str__(self):
     return 'ruby'
@@ -375,6 +405,11 @@ class PythonLanguage:
         '--args="{}"'.format(' '.join(args))
     ]
 
+  def client_cmd_http2interop(self, args):
+    return [ 'py27/bin/python',
+              'src/python/grpcio_tests/tests/http2/_negative_http2_client.py',
+           ] + args
+
   def cloud_to_prod_env(self):
     return {}
 
@@ -429,7 +464,10 @@ _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
 _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds',
                     'oauth2_auth_token', 'per_rpc_creds']
 
-_HTTP2_TEST_CASES = ["tls", "framing"]
+_HTTP2_TEST_CASES = ['tls', 'framing']
+
+_HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data',
+                     'goaway', 'ping', 'max_streams']
 
 DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
 
@@ -550,13 +588,25 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name,
 def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
                            server_port, docker_image=None):
   """Creates jobspec for cloud-to-cloud interop test"""
-  cmdline = bash_cmdline(language.client_cmd([
+  interop_only_options = [
       '--server_host_override=foo.test.google.fr',
       '--use_tls=true',
       '--use_test_ca=true',
+  ]
+  common_options = [
       '--test_case=%s' % test_case,
       '--server_host=%s' % server_host,
-      '--server_port=%s' % server_port]))
+  ]
+  if test_case in _HTTP2_BADSERVER_TEST_CASES:
+    # We are running the http2_badserver_interop test. Adjust command line accordingly.
+    offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case)
+    client_options = common_options + ['--server_port=%s' %
+                                       (int(server_port)+offset)]
+    cmdline = bash_cmdline(language.client_cmd_http2interop(client_options))
+  else:
+    client_options = interop_only_options + common_options + ['--server_port=%s' % server_port]
+    cmdline = bash_cmdline(language.client_cmd(client_options))
+
   cwd = language.client_cwd
   environ = language.global_env()
   if docker_image:
@@ -590,13 +640,30 @@ def server_jobspec(language, docker_image):
   cmdline = bash_cmdline(
       language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT]))
   environ = language.global_env()
+  if language.safename == 'http2':
+    # we are running the http2 interop server. Open next N ports beginning
+    # with the server port. These ports are used for http2 interop test
+    # (one test case per port). We also attach the docker container running
+    # the server to local network, so we don't have to mess with port mapping
+    port_args = [
+      '-p', str(_DEFAULT_SERVER_PORT+0),
+      '-p', str(_DEFAULT_SERVER_PORT+1),
+      '-p', str(_DEFAULT_SERVER_PORT+2),
+      '-p', str(_DEFAULT_SERVER_PORT+3),
+      '-p', str(_DEFAULT_SERVER_PORT+4),
+      '-p', str(_DEFAULT_SERVER_PORT+5),
+      '-p', str(_DEFAULT_SERVER_PORT+6),
+      '--net=host',
+    ]
+  else:
+    port_args = ['-p', str(_DEFAULT_SERVER_PORT)]
+
   docker_cmdline = docker_run_cmdline(cmdline,
                                       image=docker_image,
                                       cwd=language.server_cwd,
                                       environ=environ,
-                                      docker_args=['-p', str(_DEFAULT_SERVER_PORT),
-                                                   '--name', container_name])
-
+                                      docker_args=port_args +
+                                        ['--name', container_name])
   server_job = jobset.JobSpec(
           cmdline=docker_cmdline,
           environ=environ,
@@ -730,7 +797,12 @@ argp.add_argument('--http2_interop',
                   default=False,
                   action='store_const',
                   const=True,
-                  help='Enable HTTP/2 interop tests')
+                  help='Enable HTTP/2 client edge case testing. (Bad client, good server)')
+argp.add_argument('--http2_badserver_interop',
+                  default=False,
+                  action='store_const',
+                  const=True,
+                  help='Enable HTTP/2 server edge case testing. (Good client, bad server)')
 
 args = argp.parse_args()
 
@@ -757,6 +829,7 @@ languages = set(_LANGUAGES[l]
                       for x in args.language))
 
 http2Interop = Http2Client() if args.http2_interop else None
+http2InteropServer = Http2Server() if args.http2_badserver_interop else None
 
 docker_images={}
 if args.use_docker:
@@ -766,6 +839,9 @@ if args.use_docker:
   if args.http2_interop:
     languages_to_build.add(http2Interop)
 
+  if args.http2_badserver_interop:
+    languages_to_build.add(http2InteropServer)
+
   build_jobs = []
   for l in languages_to_build:
     job = build_interop_image_jobspec(l)
@@ -797,6 +873,14 @@ try:
     server_jobs[lang] = job
     server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT))
 
+  if args.http2_badserver_interop:
+    # launch a HTTP2 server emulator that creates edge cases
+    lang = str(http2InteropServer)
+    spec = server_jobspec(http2InteropServer, docker_images.get(lang))
+    job = dockerjob.DockerJob(spec)
+    server_jobs[lang] = job
+    server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT)
+
   jobs = []
   if args.cloud_to_prod:
     for server_host_name in args.prod_servers:
@@ -840,17 +924,18 @@ try:
     skip_server = []  # test cases unimplemented by server
     if server_language:
       skip_server = server_language.unimplemented_test_cases_server()
-    for language in languages:
-      for test_case in _TEST_CASES:
-        if not test_case in language.unimplemented_test_cases():
-          if not test_case in skip_server:
-            test_job = cloud_to_cloud_jobspec(language,
-                                              test_case,
-                                              server_name,
-                                              server_host,
-                                              server_port,
-                                              docker_image=docker_images.get(str(language)))
-            jobs.append(test_job)
+    if not args.http2_badserver_interop:
+      for language in languages:
+        for test_case in _TEST_CASES:
+          if not test_case in language.unimplemented_test_cases():
+            if not test_case in skip_server:
+              test_job = cloud_to_cloud_jobspec(language,
+                                                test_case,
+                                                server_name,
+                                                server_host,
+                                                server_port,
+                                                docker_image=docker_images.get(str(language)))
+              jobs.append(test_job)
 
     if args.http2_interop:
       for test_case in _HTTP2_TEST_CASES:
@@ -865,6 +950,17 @@ try:
                                           docker_image=docker_images.get(str(http2Interop)))
         jobs.append(test_job)
 
+    if args.http2_badserver_interop:
+      for language in languages:
+        for test_case in _HTTP2_BADSERVER_TEST_CASES:
+          test_job = cloud_to_cloud_jobspec(language,
+                                            test_case,
+                                            server_name,
+                                            server_host,
+                                            server_port,
+                                            docker_image=docker_images.get(str(language)))
+          jobs.append(test_job)
+
   if not jobs:
     print('No jobs to run.')
     for image in docker_images.itervalues():
diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py
index b7b742d7af2ff34cb9fad4fb59989f44472c7ac2..d6eed3f5bddcd2c0f8911aed69e4a58fc0b69629 100755
--- a/tools/run_tests/run_performance_tests.py
+++ b/tools/run_tests/run_performance_tests.py
@@ -113,7 +113,7 @@ def create_qpsworker_job(language, shortname=None, port=10000, remote_host=None,
 
 
 def create_scenario_jobspec(scenario_json, workers, remote_host=None,
-                            bq_result_table=None):
+                            bq_result_table=None, server_cpu_load=0):
   """Runs one scenario using QPS driver."""
   # setting QPS_WORKERS env variable here makes sure it works with SSH too.
   cmd = 'QPS_WORKERS="%s" ' % ','.join(workers)
@@ -121,7 +121,9 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None,
     cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table
   cmd += 'tools/run_tests/performance/run_qps_driver.sh '
   cmd += '--scenarios_json=%s ' % pipes.quote(json.dumps({'scenarios': [scenario_json]}))
-  cmd += '--scenario_result_file=scenario_result.json'
+  cmd += '--scenario_result_file=scenario_result.json '
+  if server_cpu_load != 0:
+      cmd += '--search_param=offered_load --initial_search_value=1000 --targeted_cpu_load=%d --stride=500 --error_tolerance=0.01' % server_cpu_load
   if remote_host:
     user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
     cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (user_at_host, pipes.quote(cmd))
@@ -129,7 +131,7 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None,
   return jobset.JobSpec(
       cmdline=[cmd],
       shortname='qps_json_driver.%s' % scenario_json['name'],
-      timeout_seconds=3*60,
+      timeout_seconds=12*60,
       shell=True,
       verbose_success=True)
 
@@ -318,7 +320,7 @@ Scenario = collections.namedtuple('Scenario', 'jobspec workers name')
 
 def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
                      category='all', bq_result_table=None,
-                     netperf=False, netperf_hosts=[]):
+                     netperf=False, netperf_hosts=[], server_cpu_load=0):
   """Create jobspecs for scenarios to run."""
   all_workers = [worker
                  for workers in workers_by_lang.values()
@@ -379,7 +381,8 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
               create_scenario_jobspec(scenario_json,
                                       [w.host_and_port for w in workers],
                                       remote_host=remote_host,
-                                      bq_result_table=bq_result_table),
+                                      bq_result_table=bq_result_table,
+                                      server_cpu_load=server_cpu_load),
               workers,
               scenario_json['name'])
           scenarios.append(scenario)
@@ -461,6 +464,9 @@ argp.add_argument('--netperf',
                   action='store_const',
                   const=True,
                   help='Run netperf benchmark as one of the scenarios.')
+argp.add_argument('--server_cpu_load',
+                  default=0, type=int,
+                  help='Select a targeted server cpu load to run. 0 means ignore this flag')
 argp.add_argument('-x', '--xml_report', default='report.xml', type=str,
                   help='Name of XML report file to generate.')
 argp.add_argument('--perf_args',
@@ -490,7 +496,6 @@ argp.add_argument('--skip_generate_flamegraphs',
                         'May be useful if "perf_args" arguments do not make sense for '
                         'generating flamegraphs (e.g., "--perf_args=stat ...")'))
 
-
 args = argp.parse_args()
 
 languages = set(scenario_config.LANGUAGES[l]
@@ -540,7 +545,8 @@ scenarios = create_scenarios(languages,
                            category=args.category,
                            bq_result_table=args.bq_result_table,
                            netperf=args.netperf,
-                           netperf_hosts=args.remote_worker_host)
+                           netperf_hosts=args.remote_worker_host,
+                           server_cpu_load=args.server_cpu_load)
 
 if not scenarios:
   raise Exception('No scenarios to run')
diff --git a/vsprojects/grpc.sln b/vsprojects/grpc.sln
index 63be171c6efeaae3af7320a04f5b8f05d381913b..591d3b5edb244fd4c4676415d74bd2348ead6b43 100644
--- a/vsprojects/grpc.sln
+++ b/vsprojects/grpc.sln
@@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2013
 VisualStudioVersion = 12.0.21005.1
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boringssl", "vcxproj\.\boringssl\boringssl.vcxproj", "{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}"
-	ProjectSection(myProperties) = preProject
-        	lib = "True"
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_hpack_tables", "vcxproj\.\gen_hpack_tables\gen_hpack_tables.vcxproj", "{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -56,14 +51,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++", "vcxproj\.\grpc++\
 		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_reflection", "vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj", "{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}"
-	ProjectSection(myProperties) = preProject
-        	lib = "True"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB} = {C187A093-A0FE-489D-A40A-6E33DE0F9FEB}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_unsecure", "vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj", "{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}"
 	ProjectSection(myProperties) = preProject
         	lib = "True"
@@ -161,11 +148,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tcp_server", "vcxproj\
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "z", "vcxproj\.\z\z.vcxproj", "{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}"
-	ProjectSection(myProperties) = preProject
-        	lib = "True"
-	EndProjectSection
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -178,22 +160,6 @@ Global
 		Release-DLL|x64 = Release-DLL|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|Win32.ActiveCfg = Debug|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|x64.ActiveCfg = Debug|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|Win32.ActiveCfg = Release|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|x64.ActiveCfg = Release|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|Win32.Build.0 = Debug|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|x64.Build.0 = Debug|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|Win32.Build.0 = Release|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|x64.Build.0 = Release|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|x64.Build.0 = Debug|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|Win32.Build.0 = Release|Win32
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|x64.ActiveCfg = Release|x64
-		{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|x64.Build.0 = Release|x64
 		{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|Win32.ActiveCfg = Debug|Win32
 		{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|x64.ActiveCfg = Debug|x64
 		{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Release|Win32.ActiveCfg = Release|Win32
@@ -306,22 +272,6 @@ Global
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|Win32.Build.0 = Release-DLL|Win32
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|x64.ActiveCfg = Release-DLL|x64
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|x64.Build.0 = Release-DLL|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|Win32.ActiveCfg = Debug|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|x64.ActiveCfg = Debug|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|Win32.ActiveCfg = Release|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|x64.ActiveCfg = Release|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|Win32.Build.0 = Debug|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|x64.Build.0 = Debug|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|Win32.Build.0 = Release|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|x64.Build.0 = Release|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|x64.Build.0 = Debug|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|Win32.Build.0 = Release|Win32
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|x64.ActiveCfg = Release|x64
-		{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|x64.Build.0 = Release|x64
 		{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Debug|Win32.ActiveCfg = Debug|Win32
 		{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Debug|x64.ActiveCfg = Debug|x64
 		{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Release|Win32.ActiveCfg = Release|Win32
@@ -482,22 +432,6 @@ Global
 		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.Build.0 = Release|Win32
 		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.ActiveCfg = Release|x64
 		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.Build.0 = Release|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|Win32.ActiveCfg = Debug|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|x64.ActiveCfg = Debug|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|Win32.ActiveCfg = Release|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|x64.ActiveCfg = Release|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|Win32.Build.0 = Debug|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|x64.Build.0 = Debug|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|Win32.Build.0 = Release|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|x64.Build.0 = Release|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|x64.Build.0 = Debug|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|Win32.Build.0 = Release|Win32
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|x64.ActiveCfg = Release|x64
-		{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index eeb16917cd3b3d275f4f86476f2b284c15656839..c159db63f55423581334cb7339967937fb9132cc 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -307,6 +307,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\deadline_filter.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\channel\http_client_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
@@ -497,6 +499,10 @@
     </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\channel\http_client_filter.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 14f79cae0e6ef03c42d6e1ade614833837c41b36..1e099f3285e90e1fcd32dcbf8add0b5dbe553982 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -25,6 +25,12 @@
     <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\channel\http_client_filter.c">
       <Filter>src\core\lib\channel</Filter>
     </ClCompile>
@@ -764,6 +770,12 @@
     <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\channel\http_client_filter.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index c73584a052a2eac20f5e81912589d5be00d4636b..230c3eb3dfb29bcfe13955c2c6ce995cc59bcc2c 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -200,6 +200,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\deadline_filter.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\channel\http_client_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
@@ -346,6 +348,10 @@
     </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\channel\http_client_filter.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
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 b317c142da1a53cb9cbdcdd0bf2f5cce828c5141..46a38156ea7c4e33693d5cd29473381fdaf26706 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -82,6 +82,12 @@
     <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\channel\http_client_filter.c">
       <Filter>src\core\lib\channel</Filter>
     </ClCompile>
@@ -554,6 +560,12 @@
     <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\channel\http_client_filter.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 0f57f3874eb08547cfb00a9b5fd5b91e44a9c078..dcb943a3a11b28da4b718e3bc9435184d4efb0aa 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -297,6 +297,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\deadline_filter.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\channel\http_client_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
@@ -465,6 +467,10 @@
     </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\channel\http_client_filter.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 9327bff86163d10c04ab7dca3a38d80dec968271..ac84e0188c899b58f94bc56e650f1886fbc29595 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -28,6 +28,12 @@
     <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\channel\http_client_filter.c">
       <Filter>src\core\lib\channel</Filter>
     </ClCompile>
@@ -677,6 +683,12 @@
     <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\channel\http_client_filter.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..c94c346ed9943cdbefed5bd593021661dfe5de0b
--- /dev/null
+++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj
@@ -0,0 +1,206 @@
+<?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>{8008C126-4B35-5A76-A795-39DA13DA57F4}</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>http2_client_main</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>http2_client_main</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)\..\test\cpp\interop\http2_client.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\http2_client.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</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>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</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/http2_client_main/http2_client_main.vcxproj.filters b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..40e419134510680ccc93fee67d1a132df6a0e6d4
--- /dev/null
+++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters
@@ -0,0 +1,47 @@
+<?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\empty.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.proto">
+      <Filter>src\proto\grpc\testing</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\http2_client.cc">
+      <Filter>test\cpp\interop</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\interop\http2_client.h">
+      <Filter>test\cpp\interop</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="src">
+      <UniqueIdentifier>{8f01743f-58cf-2127-20d1-21303c8e0e8e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{219dd0bc-d605-d0fa-cca4-460276dd64cf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{7ee50971-dbc6-3240-e6a2-a432dac43e90}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\testing">
+      <UniqueIdentifier>{66289b19-9541-151c-03a1-771101833b4e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{18fdd193-31a2-a622-980e-df055c23af50}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{f6da8892-ac51-d835-468a-b3b093df4baa}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\interop">
+      <UniqueIdentifier>{e32cff29-3247-cece-56cf-8fd16a1a79fe}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj
index 4c99988a34c482f55a4e8f9749ab54fa404db885..377cadc1a1ea1f4781930439f2ce36db9b9213ae 100644
--- a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj
+++ b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj
@@ -154,6 +154,9 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
       <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
     </ProjectReference>