Merge branch 'master' of github.com:grpc/grpc into lb_pollset_propagation
diff --git a/BUILD b/BUILD
index 1c40ac8..ca9ad69 100644
--- a/BUILD
+++ b/BUILD
@@ -178,7 +178,6 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
     "src/core/lib/iomgr/exec_ctx.h",
@@ -257,15 +256,24 @@
     "src/core/ext/transport/chttp2/transport/timeout_encoding.h",
     "src/core/ext/transport/chttp2/transport/varint.h",
     "src/core/ext/transport/chttp2/alpn/alpn.h",
-    "src/core/lib/security/auth_filters.h",
-    "src/core/lib/security/b64.h",
-    "src/core/lib/security/credentials.h",
-    "src/core/lib/security/handshake.h",
-    "src/core/lib/security/json_token.h",
-    "src/core/lib/security/jwt_verifier.h",
-    "src/core/lib/security/secure_endpoint.h",
-    "src/core/lib/security/security_connector.h",
-    "src/core/lib/security/security_context.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/handshake.h",
+    "src/core/lib/security/transport/secure_endpoint.h",
+    "src/core/lib/security/transport/security_connector.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",
@@ -314,7 +322,6 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
     "src/core/lib/iomgr/exec_ctx.c",
@@ -404,20 +411,28 @@
     "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/security/b64.c",
-    "src/core/lib/security/client_auth_filter.c",
-    "src/core/lib/security/credentials.c",
-    "src/core/lib/security/credentials_metadata.c",
-    "src/core/lib/security/credentials_posix.c",
-    "src/core/lib/security/credentials_win32.c",
-    "src/core/lib/security/google_default_credentials.c",
-    "src/core/lib/security/handshake.c",
-    "src/core/lib/security/json_token.c",
-    "src/core/lib/security/jwt_verifier.c",
-    "src/core/lib/security/secure_endpoint.c",
-    "src/core/lib/security/security_connector.c",
-    "src/core/lib/security/security_context.c",
-    "src/core/lib/security/server_auth_filter.c",
+    "src/core/lib/security/context/security_context.c",
+    "src/core/lib/security/credentials/composite/composite_credentials.c",
+    "src/core/lib/security/credentials/credentials.c",
+    "src/core/lib/security/credentials/credentials_metadata.c",
+    "src/core/lib/security/credentials/fake/fake_credentials.c",
+    "src/core/lib/security/credentials/google_default/credentials_posix.c",
+    "src/core/lib/security/credentials/google_default/credentials_win32.c",
+    "src/core/lib/security/credentials/google_default/google_default_credentials.c",
+    "src/core/lib/security/credentials/iam/iam_credentials.c",
+    "src/core/lib/security/credentials/jwt/json_token.c",
+    "src/core/lib/security/credentials/jwt/jwt_credentials.c",
+    "src/core/lib/security/credentials/jwt/jwt_verifier.c",
+    "src/core/lib/security/credentials/oauth2/oauth2_credentials.c",
+    "src/core/lib/security/credentials/plugin/plugin_credentials.c",
+    "src/core/lib/security/credentials/ssl/ssl_credentials.c",
+    "src/core/lib/security/transport/client_auth_filter.c",
+    "src/core/lib/security/transport/handshake.c",
+    "src/core/lib/security/transport/secure_endpoint.c",
+    "src/core/lib/security/transport/security_connector.c",
+    "src/core/lib/security/transport/server_auth_filter.c",
+    "src/core/lib/security/util/b64.c",
+    "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",
@@ -533,7 +548,6 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
     "src/core/lib/iomgr/exec_ctx.h",
@@ -655,7 +669,6 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
     "src/core/lib/iomgr/exec_ctx.c",
@@ -1349,7 +1362,6 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
     "src/core/lib/iomgr/exec_ctx.c",
@@ -1439,20 +1451,28 @@
     "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/security/b64.c",
-    "src/core/lib/security/client_auth_filter.c",
-    "src/core/lib/security/credentials.c",
-    "src/core/lib/security/credentials_metadata.c",
-    "src/core/lib/security/credentials_posix.c",
-    "src/core/lib/security/credentials_win32.c",
-    "src/core/lib/security/google_default_credentials.c",
-    "src/core/lib/security/handshake.c",
-    "src/core/lib/security/json_token.c",
-    "src/core/lib/security/jwt_verifier.c",
-    "src/core/lib/security/secure_endpoint.c",
-    "src/core/lib/security/security_connector.c",
-    "src/core/lib/security/security_context.c",
-    "src/core/lib/security/server_auth_filter.c",
+    "src/core/lib/security/context/security_context.c",
+    "src/core/lib/security/credentials/composite/composite_credentials.c",
+    "src/core/lib/security/credentials/credentials.c",
+    "src/core/lib/security/credentials/credentials_metadata.c",
+    "src/core/lib/security/credentials/fake/fake_credentials.c",
+    "src/core/lib/security/credentials/google_default/credentials_posix.c",
+    "src/core/lib/security/credentials/google_default/credentials_win32.c",
+    "src/core/lib/security/credentials/google_default/google_default_credentials.c",
+    "src/core/lib/security/credentials/iam/iam_credentials.c",
+    "src/core/lib/security/credentials/jwt/json_token.c",
+    "src/core/lib/security/credentials/jwt/jwt_credentials.c",
+    "src/core/lib/security/credentials/jwt/jwt_verifier.c",
+    "src/core/lib/security/credentials/oauth2/oauth2_credentials.c",
+    "src/core/lib/security/credentials/plugin/plugin_credentials.c",
+    "src/core/lib/security/credentials/ssl/ssl_credentials.c",
+    "src/core/lib/security/transport/client_auth_filter.c",
+    "src/core/lib/security/transport/handshake.c",
+    "src/core/lib/security/transport/secure_endpoint.c",
+    "src/core/lib/security/transport/security_connector.c",
+    "src/core/lib/security/transport/server_auth_filter.c",
+    "src/core/lib/security/util/b64.c",
+    "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",
@@ -1547,7 +1567,6 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
-    "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
     "src/core/lib/iomgr/exec_ctx.h",
@@ -1626,15 +1645,24 @@
     "src/core/ext/transport/chttp2/transport/timeout_encoding.h",
     "src/core/ext/transport/chttp2/transport/varint.h",
     "src/core/ext/transport/chttp2/alpn/alpn.h",
-    "src/core/lib/security/auth_filters.h",
-    "src/core/lib/security/b64.h",
-    "src/core/lib/security/credentials.h",
-    "src/core/lib/security/handshake.h",
-    "src/core/lib/security/json_token.h",
-    "src/core/lib/security/jwt_verifier.h",
-    "src/core/lib/security/secure_endpoint.h",
-    "src/core/lib/security/security_connector.h",
-    "src/core/lib/security/security_context.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/handshake.h",
+    "src/core/lib/security/transport/secure_endpoint.h",
+    "src/core/lib/security/transport/security_connector.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",
diff --git a/Makefile b/Makefile
index ac32da8..5156782 100644
--- a/Makefile
+++ b/Makefile
@@ -215,9 +215,9 @@
 CXX_mutrace = $(DEFAULT_CXX)
 LD_mutrace = $(DEFAULT_CC)
 LDXX_mutrace = $(DEFAULT_CXX)
-CPPFLAGS_mutrace = -O0
+CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer
 LDFLAGS_mutrace = -rdynamic
-DEFINES_mutrace = _DEBUG DEBUG
+DEFINES_mutrace = NDEBUG
 
 VALID_CONFIG_memcheck = 1
 CC_memcheck = $(DEFAULT_CC)
@@ -1000,8 +1000,6 @@
 workqueue_test: $(BINDIR)/$(CONFIG)/workqueue_test
 alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
 async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
-async_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test
-async_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test
 auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
 channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
 cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
@@ -1015,7 +1013,6 @@
 cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test
 cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test
 end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
-generic_async_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test
 generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
 golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test
 grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
@@ -1036,7 +1033,6 @@
 qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test
 qps_json_driver: $(BINDIR)/$(CONFIG)/qps_json_driver
 qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test
-qps_test: $(BINDIR)/$(CONFIG)/qps_test
 qps_worker: $(BINDIR)/$(CONFIG)/qps_worker
 reconnect_interop_client: $(BINDIR)/$(CONFIG)/reconnect_interop_client
 reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server
@@ -1049,8 +1045,6 @@
 status_test: $(BINDIR)/$(CONFIG)/status_test
 streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
 stress_test: $(BINDIR)/$(CONFIG)/stress_test
-sync_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test
-sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test
 thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
 zookeeper_test: $(BINDIR)/$(CONFIG)/zookeeper_test
 public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
@@ -1375,8 +1369,6 @@
 buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/alarm_cpp_test \
   $(BINDIR)/$(CONFIG)/async_end2end_test \
-  $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test \
-  $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
   $(BINDIR)/$(CONFIG)/channel_arguments_test \
   $(BINDIR)/$(CONFIG)/cli_call_test \
@@ -1390,7 +1382,6 @@
   $(BINDIR)/$(CONFIG)/cxx_string_ref_test \
   $(BINDIR)/$(CONFIG)/cxx_time_test \
   $(BINDIR)/$(CONFIG)/end2end_test \
-  $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test \
   $(BINDIR)/$(CONFIG)/generic_end2end_test \
   $(BINDIR)/$(CONFIG)/golden_file_test \
   $(BINDIR)/$(CONFIG)/grpc_cli \
@@ -1405,7 +1396,6 @@
   $(BINDIR)/$(CONFIG)/qps_interarrival_test \
   $(BINDIR)/$(CONFIG)/qps_json_driver \
   $(BINDIR)/$(CONFIG)/qps_openloop_test \
-  $(BINDIR)/$(CONFIG)/qps_test \
   $(BINDIR)/$(CONFIG)/qps_worker \
   $(BINDIR)/$(CONFIG)/reconnect_interop_client \
   $(BINDIR)/$(CONFIG)/reconnect_interop_server \
@@ -1418,8 +1408,6 @@
   $(BINDIR)/$(CONFIG)/status_test \
   $(BINDIR)/$(CONFIG)/streaming_throughput_test \
   $(BINDIR)/$(CONFIG)/stress_test \
-  $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test \
-  $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
   $(BINDIR)/$(CONFIG)/boringssl_aes_test \
   $(BINDIR)/$(CONFIG)/boringssl_asn1_test \
@@ -1695,10 +1683,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/alarm_cpp_test || ( echo test alarm_cpp_test failed ; exit 1 )
 	$(E) "[RUN]     Testing async_end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
-	$(E) "[RUN]     Testing async_streaming_ping_pong_test"
-	$(Q) $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test || ( echo test async_streaming_ping_pong_test failed ; exit 1 )
-	$(E) "[RUN]     Testing async_unary_ping_pong_test"
-	$(Q) $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test || ( echo test async_unary_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing auth_property_iterator_test"
 	$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_arguments_test"
@@ -1723,8 +1707,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/cxx_time_test || ( echo test cxx_time_test failed ; exit 1 )
 	$(E) "[RUN]     Testing end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 )
-	$(E) "[RUN]     Testing generic_async_streaming_ping_pong_test"
-	$(Q) $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test || ( echo test generic_async_streaming_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing generic_end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
 	$(E) "[RUN]     Testing golden_file_test"
@@ -1739,8 +1721,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/mock_test || ( echo test mock_test failed ; exit 1 )
 	$(E) "[RUN]     Testing qps_openloop_test"
 	$(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 )
-	$(E) "[RUN]     Testing qps_test"
-	$(Q) $(BINDIR)/$(CONFIG)/qps_test || ( echo test qps_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_auth_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_sync_unary_ping_pong_test"
@@ -1755,10 +1735,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/status_test || ( echo test status_test failed ; exit 1 )
 	$(E) "[RUN]     Testing streaming_throughput_test"
 	$(Q) $(BINDIR)/$(CONFIG)/streaming_throughput_test || ( echo test streaming_throughput_test failed ; exit 1 )
-	$(E) "[RUN]     Testing sync_streaming_ping_pong_test"
-	$(Q) $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test || ( echo test sync_streaming_ping_pong_test failed ; exit 1 )
-	$(E) "[RUN]     Testing sync_unary_ping_pong_test"
-	$(Q) $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test || ( echo test sync_unary_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing thread_stress_test"
 	$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
 
@@ -1872,7 +1848,7 @@
 $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
 	$(E) "[MAKE]    Generating $@"
 	$(Q) mkdir -p $(@D)
-	$(Q) echo -e "$(GRPC_ZOOKEEPER_PC_FILE)" >$@
+	$(Q) echo "$(GRPC_ZOOKEEPER_PC_FILE)" | tr , '\n' >$@
 
 $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc:
 	$(E) "[MAKE]    Generating $@"
@@ -2510,7 +2486,6 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
-    src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
     src/core/lib/iomgr/exec_ctx.c \
@@ -2600,20 +2575,28 @@
     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/security/b64.c \
-    src/core/lib/security/client_auth_filter.c \
-    src/core/lib/security/credentials.c \
-    src/core/lib/security/credentials_metadata.c \
-    src/core/lib/security/credentials_posix.c \
-    src/core/lib/security/credentials_win32.c \
-    src/core/lib/security/google_default_credentials.c \
-    src/core/lib/security/handshake.c \
-    src/core/lib/security/json_token.c \
-    src/core/lib/security/jwt_verifier.c \
-    src/core/lib/security/secure_endpoint.c \
-    src/core/lib/security/security_connector.c \
-    src/core/lib/security/security_context.c \
-    src/core/lib/security/server_auth_filter.c \
+    src/core/lib/security/context/security_context.c \
+    src/core/lib/security/credentials/composite/composite_credentials.c \
+    src/core/lib/security/credentials/credentials.c \
+    src/core/lib/security/credentials/credentials_metadata.c \
+    src/core/lib/security/credentials/fake/fake_credentials.c \
+    src/core/lib/security/credentials/google_default/credentials_posix.c \
+    src/core/lib/security/credentials/google_default/credentials_win32.c \
+    src/core/lib/security/credentials/google_default/google_default_credentials.c \
+    src/core/lib/security/credentials/iam/iam_credentials.c \
+    src/core/lib/security/credentials/jwt/json_token.c \
+    src/core/lib/security/credentials/jwt/jwt_credentials.c \
+    src/core/lib/security/credentials/jwt/jwt_verifier.c \
+    src/core/lib/security/credentials/oauth2/oauth2_credentials.c \
+    src/core/lib/security/credentials/plugin/plugin_credentials.c \
+    src/core/lib/security/credentials/ssl/ssl_credentials.c \
+    src/core/lib/security/transport/client_auth_filter.c \
+    src/core/lib/security/transport/handshake.c \
+    src/core/lib/security/transport/secure_endpoint.c \
+    src/core/lib/security/transport/security_connector.c \
+    src/core/lib/security/transport/server_auth_filter.c \
+    src/core/lib/security/util/b64.c \
+    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 \
@@ -2858,7 +2841,6 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
-    src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
     src/core/lib/iomgr/exec_ctx.c \
@@ -9719,92 +9701,6 @@
 endif
 
 
-ASYNC_STREAMING_PING_PONG_TEST_SRC = \
-    test/cpp/qps/async_streaming_ping_pong_test.cc \
-
-ASYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_STREAMING_PING_PONG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test: $(PROTOBUF_DEP) $(ASYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(ASYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/async_streaming_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_async_streaming_ping_pong_test: $(ASYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(ASYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
-ASYNC_UNARY_PING_PONG_TEST_SRC = \
-    test/cpp/qps/async_unary_ping_pong_test.cc \
-
-ASYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_UNARY_PING_PONG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/async_unary_ping_pong_test: $(PROTOBUF_DEP) $(ASYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(ASYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/async_unary_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_async_unary_ping_pong_test: $(ASYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(ASYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 AUTH_PROPERTY_ITERATOR_TEST_SRC = \
     test/cpp/common/auth_property_iterator_test.cc \
 
@@ -10410,49 +10306,6 @@
 endif
 
 
-GENERIC_ASYNC_STREAMING_PING_PONG_TEST_SRC = \
-    test/cpp/qps/generic_async_streaming_ping_pong_test.cc \
-
-GENERIC_ASYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GENERIC_ASYNC_STREAMING_PING_PONG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test: $(PROTOBUF_DEP) $(GENERIC_ASYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(GENERIC_ASYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/generic_async_streaming_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_generic_async_streaming_ping_pong_test: $(GENERIC_ASYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(GENERIC_ASYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 GENERIC_END2END_TEST_SRC = \
     test/cpp/end2end/generic_end2end_test.cc \
 
@@ -11232,49 +11085,6 @@
 endif
 
 
-QPS_TEST_SRC = \
-    test/cpp/qps/qps_test.cc \
-
-QPS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/qps_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/qps_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/qps_test: $(PROTOBUF_DEP) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(QPS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
-
-deps_qps_test: $(QPS_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(QPS_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 QPS_WORKER_SRC = \
     test/cpp/qps/worker.cc \
 
@@ -11836,92 +11646,6 @@
 $(OBJDIR)/$(CONFIG)/test/cpp/util/metrics_server.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/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
 
 
-SYNC_STREAMING_PING_PONG_TEST_SRC = \
-    test/cpp/qps/sync_streaming_ping_pong_test.cc \
-
-SYNC_STREAMING_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_STREAMING_PING_PONG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test: $(PROTOBUF_DEP) $(SYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(SYNC_STREAMING_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/sync_streaming_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_sync_streaming_ping_pong_test: $(SYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(SYNC_STREAMING_PING_PONG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
-SYNC_UNARY_PING_PONG_TEST_SRC = \
-    test/cpp/qps/sync_unary_ping_pong_test.cc \
-
-SYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SYNC_UNARY_PING_PONG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/sync_unary_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_sync_unary_ping_pong_test: $(SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 THREAD_STRESS_TEST_SRC = \
     test/cpp/end2end/thread_stress_test.cc \
 
@@ -14411,20 +14135,28 @@
 src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP)
 src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP)
 src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP)
-src/core/lib/security/b64.c: $(OPENSSL_DEP)
-src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP)
-src/core/lib/security/credentials.c: $(OPENSSL_DEP)
-src/core/lib/security/credentials_metadata.c: $(OPENSSL_DEP)
-src/core/lib/security/credentials_posix.c: $(OPENSSL_DEP)
-src/core/lib/security/credentials_win32.c: $(OPENSSL_DEP)
-src/core/lib/security/google_default_credentials.c: $(OPENSSL_DEP)
-src/core/lib/security/handshake.c: $(OPENSSL_DEP)
-src/core/lib/security/json_token.c: $(OPENSSL_DEP)
-src/core/lib/security/jwt_verifier.c: $(OPENSSL_DEP)
-src/core/lib/security/secure_endpoint.c: $(OPENSSL_DEP)
-src/core/lib/security/security_connector.c: $(OPENSSL_DEP)
-src/core/lib/security/security_context.c: $(OPENSSL_DEP)
-src/core/lib/security/server_auth_filter.c: $(OPENSSL_DEP)
+src/core/lib/security/context/security_context.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/composite/composite_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/credentials_metadata.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/fake/fake_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/google_default/credentials_posix.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/google_default/credentials_win32.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/google_default/google_default_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/iam/iam_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/jwt/json_token.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/jwt/jwt_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/jwt/jwt_verifier.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/handshake.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP)
+src/core/lib/security/util/b64.c: $(OPENSSL_DEP)
+src/core/lib/security/util/json_util.c: $(OPENSSL_DEP)
 src/core/lib/surface/init_secure.c: $(OPENSSL_DEP)
 src/core/lib/tsi/fake_transport_security.c: $(OPENSSL_DEP)
 src/core/lib/tsi/ssl_transport_security.c: $(OPENSSL_DEP)
diff --git a/README.md b/README.md
index 3ee2b9f..3283517 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,12 @@
 
 You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively.
 
-#Installation
+#Installation & Testing
 
 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)
+
 #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 3bc75dd..90b50cb 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -581,7 +581,6 @@
         'src/core/lib/iomgr/endpoint.c',
         'src/core/lib/iomgr/endpoint_pair_posix.c',
         'src/core/lib/iomgr/endpoint_pair_windows.c',
-        'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
         'src/core/lib/iomgr/ev_poll_posix.c',
         'src/core/lib/iomgr/ev_posix.c',
         'src/core/lib/iomgr/exec_ctx.c',
@@ -671,20 +670,28 @@
         '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/security/b64.c',
-        'src/core/lib/security/client_auth_filter.c',
-        'src/core/lib/security/credentials.c',
-        'src/core/lib/security/credentials_metadata.c',
-        'src/core/lib/security/credentials_posix.c',
-        'src/core/lib/security/credentials_win32.c',
-        'src/core/lib/security/google_default_credentials.c',
-        'src/core/lib/security/handshake.c',
-        'src/core/lib/security/json_token.c',
-        'src/core/lib/security/jwt_verifier.c',
-        'src/core/lib/security/secure_endpoint.c',
-        'src/core/lib/security/security_connector.c',
-        'src/core/lib/security/security_context.c',
-        'src/core/lib/security/server_auth_filter.c',
+        'src/core/lib/security/context/security_context.c',
+        'src/core/lib/security/credentials/composite/composite_credentials.c',
+        'src/core/lib/security/credentials/credentials.c',
+        'src/core/lib/security/credentials/credentials_metadata.c',
+        'src/core/lib/security/credentials/fake/fake_credentials.c',
+        'src/core/lib/security/credentials/google_default/credentials_posix.c',
+        'src/core/lib/security/credentials/google_default/credentials_win32.c',
+        'src/core/lib/security/credentials/google_default/google_default_credentials.c',
+        'src/core/lib/security/credentials/iam/iam_credentials.c',
+        'src/core/lib/security/credentials/jwt/json_token.c',
+        'src/core/lib/security/credentials/jwt/jwt_credentials.c',
+        'src/core/lib/security/credentials/jwt/jwt_verifier.c',
+        'src/core/lib/security/credentials/oauth2/oauth2_credentials.c',
+        'src/core/lib/security/credentials/plugin/plugin_credentials.c',
+        'src/core/lib/security/credentials/ssl/ssl_credentials.c',
+        'src/core/lib/security/transport/client_auth_filter.c',
+        'src/core/lib/security/transport/handshake.c',
+        'src/core/lib/security/transport/secure_endpoint.c',
+        'src/core/lib/security/transport/security_connector.c',
+        'src/core/lib/security/transport/server_auth_filter.c',
+        'src/core/lib/security/util/b64.c',
+        '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',
diff --git a/build.yaml b/build.yaml
index 0d77be0..b20df2a 100644
--- a/build.yaml
+++ b/build.yaml
@@ -165,7 +165,6 @@
   - src/core/lib/iomgr/closure.h
   - src/core/lib/iomgr/endpoint.h
   - src/core/lib/iomgr/endpoint_pair.h
-  - src/core/lib/iomgr/ev_poll_and_epoll_posix.h
   - src/core/lib/iomgr/ev_poll_posix.h
   - src/core/lib/iomgr/ev_posix.h
   - src/core/lib/iomgr/exec_ctx.h
@@ -241,7 +240,6 @@
   - src/core/lib/iomgr/endpoint.c
   - src/core/lib/iomgr/endpoint_pair_posix.c
   - src/core/lib/iomgr/endpoint_pair_windows.c
-  - src/core/lib/iomgr/ev_poll_and_epoll_posix.c
   - src/core/lib/iomgr/ev_poll_posix.c
   - src/core/lib/iomgr/ev_posix.c
   - src/core/lib/iomgr/exec_ctx.c
@@ -408,31 +406,48 @@
   - include/grpc/grpc_security.h
   - include/grpc/grpc_security_constants.h
   headers:
-  - src/core/lib/security/auth_filters.h
-  - src/core/lib/security/b64.h
-  - src/core/lib/security/credentials.h
-  - src/core/lib/security/handshake.h
-  - src/core/lib/security/json_token.h
-  - src/core/lib/security/jwt_verifier.h
-  - src/core/lib/security/secure_endpoint.h
-  - src/core/lib/security/security_connector.h
-  - src/core/lib/security/security_context.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/handshake.h
+  - src/core/lib/security/transport/secure_endpoint.h
+  - src/core/lib/security/transport/security_connector.h
+  - src/core/lib/security/util/b64.h
+  - src/core/lib/security/util/json_util.h
   src:
   - src/core/lib/http/httpcli_security_connector.c
-  - src/core/lib/security/b64.c
-  - src/core/lib/security/client_auth_filter.c
-  - src/core/lib/security/credentials.c
-  - src/core/lib/security/credentials_metadata.c
-  - src/core/lib/security/credentials_posix.c
-  - src/core/lib/security/credentials_win32.c
-  - src/core/lib/security/google_default_credentials.c
-  - src/core/lib/security/handshake.c
-  - src/core/lib/security/json_token.c
-  - src/core/lib/security/jwt_verifier.c
-  - src/core/lib/security/secure_endpoint.c
-  - src/core/lib/security/security_connector.c
-  - src/core/lib/security/security_context.c
-  - src/core/lib/security/server_auth_filter.c
+  - src/core/lib/security/context/security_context.c
+  - src/core/lib/security/credentials/composite/composite_credentials.c
+  - src/core/lib/security/credentials/credentials.c
+  - src/core/lib/security/credentials/credentials_metadata.c
+  - src/core/lib/security/credentials/fake/fake_credentials.c
+  - src/core/lib/security/credentials/google_default/credentials_posix.c
+  - src/core/lib/security/credentials/google_default/credentials_win32.c
+  - src/core/lib/security/credentials/google_default/google_default_credentials.c
+  - src/core/lib/security/credentials/iam/iam_credentials.c
+  - src/core/lib/security/credentials/jwt/json_token.c
+  - src/core/lib/security/credentials/jwt/jwt_credentials.c
+  - src/core/lib/security/credentials/jwt/jwt_verifier.c
+  - src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+  - src/core/lib/security/credentials/plugin/plugin_credentials.c
+  - src/core/lib/security/credentials/ssl/ssl_credentials.c
+  - src/core/lib/security/transport/client_auth_filter.c
+  - src/core/lib/security/transport/handshake.c
+  - src/core/lib/security/transport/secure_endpoint.c
+  - src/core/lib/security/transport/security_connector.c
+  - src/core/lib/security/transport/server_auth_filter.c
+  - src/core/lib/security/util/b64.c
+  - src/core/lib/security/util/json_util.c
   - src/core/lib/surface/init_secure.c
   secure: true
   uses:
@@ -2341,40 +2356,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: async_streaming_ping_pong_test
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/async_streaming_ping_pong_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  platforms:
-  - mac
-  - linux
-  - posix
-- name: async_unary_ping_pong_test
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/async_unary_ping_pong_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  platforms:
-  - mac
-  - linux
-  - posix
 - name: auth_property_iterator_test
   gtest: true
   build: test
@@ -2542,23 +2523,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: generic_async_streaming_ping_pong_test
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/generic_async_streaming_ping_pong_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  platforms:
-  - mac
-  - linux
-  - posix
 - name: generic_end2end_test
   gtest: true
   build: test
@@ -2830,25 +2794,6 @@
   - mac
   - linux
   - posix
-- name: qps_test
-  cpu_cost: 10
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/qps_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  - grpc++_test_config
-  platforms:
-  - mac
-  - linux
-  - posix
 - name: qps_worker
   build: test
   run: false
@@ -3044,40 +2989,6 @@
   - gpr_test_util
   - gpr
   - grpc++_test_config
-- name: sync_streaming_ping_pong_test
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/sync_streaming_ping_pong_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  platforms:
-  - mac
-  - linux
-  - posix
-- name: sync_unary_ping_pong_test
-  build: test
-  language: c++
-  src:
-  - test/cpp/qps/sync_unary_ping_pong_test.cc
-  deps:
-  - qps
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc
-  - gpr_test_util
-  - gpr
-  platforms:
-  - mac
-  - linux
-  - posix
 - name: thread_stress_test
   gtest: true
   cpu_cost: 100
@@ -3248,8 +3159,8 @@
     compile_the_world: true
     timeout_multiplier: 4
   mutrace:
-    CPPFLAGS: -O0
-    DEFINES: _DEBUG DEBUG
+    CPPFLAGS: -O3 -fno-omit-frame-pointer
+    DEFINES: NDEBUG
     LDFLAGS: -rdynamic
   opt:
     CPPFLAGS: -O2
@@ -3280,7 +3191,7 @@
     LDXX: clang++
     compile_the_world: true
     test_environ:
-      UBSAN_OPTIONS: print_stacktrace=1
+      UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
     timeout_multiplier: 1.5
 defaults:
   boringssl:
diff --git a/config.m4 b/config.m4
index eb96d20..8d50b54 100644
--- a/config.m4
+++ b/config.m4
@@ -100,7 +100,6 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
-    src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
     src/core/lib/iomgr/exec_ctx.c \
@@ -190,20 +189,28 @@
     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/security/b64.c \
-    src/core/lib/security/client_auth_filter.c \
-    src/core/lib/security/credentials.c \
-    src/core/lib/security/credentials_metadata.c \
-    src/core/lib/security/credentials_posix.c \
-    src/core/lib/security/credentials_win32.c \
-    src/core/lib/security/google_default_credentials.c \
-    src/core/lib/security/handshake.c \
-    src/core/lib/security/json_token.c \
-    src/core/lib/security/jwt_verifier.c \
-    src/core/lib/security/secure_endpoint.c \
-    src/core/lib/security/security_connector.c \
-    src/core/lib/security/security_context.c \
-    src/core/lib/security/server_auth_filter.c \
+    src/core/lib/security/context/security_context.c \
+    src/core/lib/security/credentials/composite/composite_credentials.c \
+    src/core/lib/security/credentials/credentials.c \
+    src/core/lib/security/credentials/credentials_metadata.c \
+    src/core/lib/security/credentials/fake/fake_credentials.c \
+    src/core/lib/security/credentials/google_default/credentials_posix.c \
+    src/core/lib/security/credentials/google_default/credentials_win32.c \
+    src/core/lib/security/credentials/google_default/google_default_credentials.c \
+    src/core/lib/security/credentials/iam/iam_credentials.c \
+    src/core/lib/security/credentials/jwt/json_token.c \
+    src/core/lib/security/credentials/jwt/jwt_credentials.c \
+    src/core/lib/security/credentials/jwt/jwt_verifier.c \
+    src/core/lib/security/credentials/oauth2/oauth2_credentials.c \
+    src/core/lib/security/credentials/plugin/plugin_credentials.c \
+    src/core/lib/security/credentials/ssl/ssl_credentials.c \
+    src/core/lib/security/transport/client_auth_filter.c \
+    src/core/lib/security/transport/handshake.c \
+    src/core/lib/security/transport/secure_endpoint.c \
+    src/core/lib/security/transport/security_connector.c \
+    src/core/lib/security/transport/server_auth_filter.c \
+    src/core/lib/security/util/b64.c \
+    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 \
@@ -580,7 +587,18 @@
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/composite)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/fake)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/google_default)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/iam)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/jwt)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/oauth2)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/plugin)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/ssl)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/transport)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/util)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/support)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/surface)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport)
diff --git a/doc/connectivity-semantics-and-api.md b/doc/connectivity-semantics-and-api.md
index 5427900..cc007ea 100644
--- a/doc/connectivity-semantics-and-api.md
+++ b/doc/connectivity-semantics-and-api.md
@@ -101,7 +101,7 @@
     <td>Shutdown triggered by application.</td>
   </tr>
   <tr>
-    <th>FATAL_FAILURE</th>
+    <th>SHUTDOWN</th>
     <td></td>
     <td></td>
     <td></td>
diff --git a/examples/cpp/helloworld/Makefile b/examples/cpp/helloworld/Makefile
index 58a82db..780e5e4 100644
--- a/examples/cpp/helloworld/Makefile
+++ b/examples/cpp/helloworld/Makefile
@@ -32,7 +32,7 @@
 CXX = g++
 CPPFLAGS += -I/usr/local/include -pthread
 CXXFLAGS += -std=c++11
-LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` -lprotobuf -lpthread -ldl
+LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` -lprotobuf -lpthread -ldl
 PROTOC = protoc
 GRPC_CPP_PLUGIN = grpc_cpp_plugin
 GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
diff --git a/examples/csharp/helloworld/.nuget/packages.config b/examples/csharp/helloworld/.nuget/packages.config
index 0f89a66..bfd6c67 100644
--- a/examples/csharp/helloworld/.nuget/packages.config
+++ b/examples/csharp/helloworld/.nuget/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Grpc.Tools" version="0.13.1" />
+  <package id="Grpc.Tools" version="0.14.0" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/Greeter/Greeter.csproj b/examples/csharp/helloworld/Greeter/Greeter.csproj
index 1e9399f..0270cc2 100644
--- a/examples/csharp/helloworld/Greeter/Greeter.csproj
+++ b/examples/csharp/helloworld/Greeter/Greeter.csproj
@@ -10,7 +10,7 @@
     <RootNamespace>Greeter</RootNamespace>
     <AssemblyName>Greeter</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>96275748</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>745ac60f</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -35,9 +35,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -61,11 +61,11 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup />
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/Greeter/HelloworldGrpc.cs b/examples/csharp/helloworld/Greeter/HelloworldGrpc.cs
index 4014bc2..405f3bd 100644
--- a/examples/csharp/helloworld/Greeter/HelloworldGrpc.cs
+++ b/examples/csharp/helloworld/Greeter/HelloworldGrpc.cs
@@ -1,5 +1,35 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: helloworld.proto
+// Original file comments:
+// Copyright 2015, 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.
+//
 #region Designer generated code
 
 using System;
@@ -8,6 +38,9 @@
 using Grpc.Core;
 
 namespace Helloworld {
+  /// <summary>
+  ///  The greeting service definition.
+  /// </summary>
   public static class Greeter
   {
     static readonly string __ServiceName = "helloworld.Greeter";
@@ -22,66 +55,133 @@
         __Marshaller_HelloRequest,
         __Marshaller_HelloReply);
 
-    // service descriptor
+    /// <summary>Service descriptor</summary>
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     {
       get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; }
     }
 
-    // client interface
+    /// <summary>Client for Greeter</summary>
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IGreeterClient
     {
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
       global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
       global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options);
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
       AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
       AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options);
     }
 
-    // server-side interface
+    /// <summary>Interface of server-side implementations of Greeter</summary>
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IGreeter
     {
-      Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context);
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      global::System.Threading.Tasks.Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context);
     }
 
-    // client stub
-    public class GreeterClient : ClientBase, IGreeterClient
+    /// <summary>Base class for server-side implementations of Greeter</summary>
+    public abstract class GreeterBase
+    {
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      public virtual global::System.Threading.Tasks.Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for Greeter</summary>
+    #pragma warning disable 0618
+    public class GreeterClient : ClientBase<GreeterClient>, IGreeterClient
+    #pragma warning restore 0618
     {
       public GreeterClient(Channel channel) : base(channel)
       {
       }
-      public global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public GreeterClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_SayHello, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected GreeterClient() : base()
       {
-        var call = CreateCall(__Method_SayHello, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_SayHello, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options)
+
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_SayHello, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return SayHello(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request);
+      }
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      ///  Sends a greeting
+      /// </summary>
+      public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request);
+      }
+      protected override GreeterClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new GreeterClient(configuration);
       }
     }
 
-    // creates service definition that can be registered with a server
+    /// <summary>Creates a new client for Greeter</summary>
+    public static GreeterClient NewClient(Channel channel)
+    {
+      return new GreeterClient(channel);
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    #pragma warning disable 0618
     public static ServerServiceDefinition BindService(IGreeter serviceImpl)
+    #pragma warning restore 0618
     {
       return ServerServiceDefinition.CreateBuilder(__ServiceName)
           .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build();
     }
 
-    // creates a new client
-    public static GreeterClient NewClient(Channel channel)
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    #pragma warning disable 0618
+    public static ServerServiceDefinition BindService(GreeterBase serviceImpl)
+    #pragma warning restore 0618
     {
-      return new GreeterClient(channel);
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build();
     }
 
   }
diff --git a/examples/csharp/helloworld/Greeter/packages.config b/examples/csharp/helloworld/Greeter/packages.config
index 7d24440..617fe6d 100644
--- a/examples/csharp/helloworld/Greeter/packages.config
+++ b/examples/csharp/helloworld/Greeter/packages.config
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterClient/GreeterClient.csproj b/examples/csharp/helloworld/GreeterClient/GreeterClient.csproj
index e10a605..877c450 100644
--- a/examples/csharp/helloworld/GreeterClient/GreeterClient.csproj
+++ b/examples/csharp/helloworld/GreeterClient/GreeterClient.csproj
@@ -10,7 +10,7 @@
     <RootNamespace>GreeterClient</RootNamespace>
     <AssemblyName>GreeterClient</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>d94f6f5f</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>63b59176</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -35,9 +35,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -59,11 +59,11 @@
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterClient/packages.config b/examples/csharp/helloworld/GreeterClient/packages.config
index 7d24440..617fe6d 100644
--- a/examples/csharp/helloworld/GreeterClient/packages.config
+++ b/examples/csharp/helloworld/GreeterClient/packages.config
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterServer/GreeterServer.csproj b/examples/csharp/helloworld/GreeterServer/GreeterServer.csproj
index 6c70f75..4d792dc 100644
--- a/examples/csharp/helloworld/GreeterServer/GreeterServer.csproj
+++ b/examples/csharp/helloworld/GreeterServer/GreeterServer.csproj
@@ -10,7 +10,7 @@
     <RootNamespace>GreeterServer</RootNamespace>
     <AssemblyName>GreeterServer</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <NuGetPackageImportStamp>6f89e9f2</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>25ac2e80</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -35,9 +35,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -59,11 +59,11 @@
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/GreeterServer/Program.cs b/examples/csharp/helloworld/GreeterServer/Program.cs
index 79f421d..fdab379 100644
--- a/examples/csharp/helloworld/GreeterServer/Program.cs
+++ b/examples/csharp/helloworld/GreeterServer/Program.cs
@@ -34,10 +34,10 @@
 
 namespace GreeterServer
 {
-    class GreeterImpl : Greeter.IGreeter
+    class GreeterImpl : Greeter.GreeterBase
     {
         // Server side handler of the SayHello RPC
-        public Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
+        public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
         {
             return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
         }
diff --git a/examples/csharp/helloworld/GreeterServer/packages.config b/examples/csharp/helloworld/GreeterServer/packages.config
index 7d24440..617fe6d 100644
--- a/examples/csharp/helloworld/GreeterServer/packages.config
+++ b/examples/csharp/helloworld/GreeterServer/packages.config
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/helloworld/generate_protos.bat b/examples/csharp/helloworld/generate_protos.bat
index 3be1ceb..b9f68d6 100644
--- a/examples/csharp/helloworld/generate_protos.bat
+++ b/examples/csharp/helloworld/generate_protos.bat
@@ -34,7 +34,7 @@
 @rem enter this directory
 cd /d %~dp0
 
-set TOOLS_PATH=packages\Grpc.Tools.0.13.1\tools\windows_x86
+set TOOLS_PATH=packages\Grpc.Tools.0.14.0\tools\windows_x86
 
 %TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter  ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
 
diff --git a/examples/csharp/route_guide/.nuget/packages.config b/examples/csharp/route_guide/.nuget/packages.config
index 0f89a66..bfd6c67 100644
--- a/examples/csharp/route_guide/.nuget/packages.config
+++ b/examples/csharp/route_guide/.nuget/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Grpc.Tools" version="0.13.1" />
+  <package id="Grpc.Tools" version="0.14.0" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj b/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
index eba1226..4f7222e 100644
--- a/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
+++ b/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
@@ -11,7 +11,7 @@
     <AssemblyName>RouteGuide</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>e1e648e7</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>0a9fcb7a</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -35,9 +35,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -74,12 +74,12 @@
     </None>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs b/examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs
index 66d1c07..a59906d 100644
--- a/examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs
+++ b/examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs
@@ -1,5 +1,35 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: route_guide.proto
+// Original file comments:
+// Copyright 2015, 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.
+//
 #region Designer generated code
 
 using System;
@@ -8,6 +38,9 @@
 using Grpc.Core;
 
 namespace Routeguide {
+  /// <summary>
+  ///  Interface exported by the server.
+  /// </summary>
   public static class RouteGuide
   {
     static readonly string __ServiceName = "routeguide.RouteGuide";
@@ -46,96 +79,339 @@
         __Marshaller_RouteNote,
         __Marshaller_RouteNote);
 
-    // service descriptor
+    /// <summary>Service descriptor</summary>
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     {
       get { return global::Routeguide.RouteGuideReflection.Descriptor.Services[0]; }
     }
 
-    // client interface
+    /// <summary>Client for RouteGuide</summary>
+    [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
     public interface IRouteGuideClient
     {
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
       global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
       global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options);
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
       AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
       AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options);
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
       AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
       AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options);
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
       AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
       AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options);
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
       AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
       AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options);
     }
 
-    // server-side interface
+    /// <summary>Interface of server-side implementations of RouteGuide</summary>
+    [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
     public interface IRouteGuide
     {
-      Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, ServerCallContext context);
-      Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter<global::Routeguide.Feature> responseStream, ServerCallContext context);
-      Task<global::Routeguide.RouteSummary> RecordRoute(IAsyncStreamReader<global::Routeguide.Point> requestStream, ServerCallContext context);
-      Task RouteChat(IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, IServerStreamWriter<global::Routeguide.RouteNote> responseStream, ServerCallContext context);
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      global::System.Threading.Tasks.Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, ServerCallContext context);
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
+      global::System.Threading.Tasks.Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter<global::Routeguide.Feature> responseStream, ServerCallContext context);
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
+      global::System.Threading.Tasks.Task<global::Routeguide.RouteSummary> RecordRoute(IAsyncStreamReader<global::Routeguide.Point> requestStream, ServerCallContext context);
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
+      global::System.Threading.Tasks.Task RouteChat(IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, IServerStreamWriter<global::Routeguide.RouteNote> responseStream, ServerCallContext context);
     }
 
-    // client stub
-    public class RouteGuideClient : ClientBase, IRouteGuideClient
+    /// <summary>Base class for server-side implementations of RouteGuide</summary>
+    public abstract class RouteGuideBase
+    {
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      public virtual global::System.Threading.Tasks.Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
+      public virtual global::System.Threading.Tasks.Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter<global::Routeguide.Feature> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
+      public virtual global::System.Threading.Tasks.Task<global::Routeguide.RouteSummary> RecordRoute(IAsyncStreamReader<global::Routeguide.Point> requestStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
+      public virtual global::System.Threading.Tasks.Task RouteChat(IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, IServerStreamWriter<global::Routeguide.RouteNote> responseStream, ServerCallContext context)
+      {
+        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for RouteGuide</summary>
+    #pragma warning disable 0618
+    public class RouteGuideClient : ClientBase<RouteGuideClient>, IRouteGuideClient
+    #pragma warning restore 0618
     {
       public RouteGuideClient(Channel channel) : base(channel)
       {
       }
-      public global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public RouteGuideClient(CallInvoker callInvoker) : base(callInvoker)
       {
-        var call = CreateCall(__Method_GetFeature, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options)
+      ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected RouteGuideClient() : base()
       {
-        var call = CreateCall(__Method_GetFeature, options);
-        return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      ///<summary>Protected constructor to allow creation of configured clients.</summary>
+      protected RouteGuideClient(ClientBaseConfiguration configuration) : base(configuration)
       {
-        var call = CreateCall(__Method_GetFeature, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options)
+
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_GetFeature, options);
-        return Calls.AsyncUnaryCall(call, request);
+        return GetFeature(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options)
       {
-        var call = CreateCall(__Method_ListFeatures, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncServerStreamingCall(call, request);
+        return CallInvoker.BlockingUnaryCall(__Method_GetFeature, null, options, request);
       }
-      public AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options)
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      public virtual AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_ListFeatures, options);
-        return Calls.AsyncServerStreamingCall(call, request);
+        return GetFeatureAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      /// <summary>
+      ///  A simple RPC.
+      ///
+      ///  Obtains the feature at a given position.
+      ///
+      ///  A feature with an empty name is returned if there's no feature at the given
+      ///  position.
+      /// </summary>
+      public virtual AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options)
       {
-        var call = CreateCall(__Method_RecordRoute, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncClientStreamingCall(call);
+        return CallInvoker.AsyncUnaryCall(__Method_GetFeature, null, options, request);
       }
-      public AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options)
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
+      public virtual AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_RecordRoute, options);
-        return Calls.AsyncClientStreamingCall(call);
+        return ListFeatures(request, new CallOptions(headers, deadline, cancellationToken));
       }
-      public AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      /// <summary>
+      ///  A server-to-client streaming RPC.
+      ///
+      ///  Obtains the Features available within the given Rectangle.  Results are
+      ///  streamed rather than returned at once (e.g. in a response message with a
+      ///  repeated field), as the rectangle may cover a large area and contain a
+      ///  huge number of features.
+      /// </summary>
+      public virtual AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options)
       {
-        var call = CreateCall(__Method_RouteChat, new CallOptions(headers, deadline, cancellationToken));
-        return Calls.AsyncDuplexStreamingCall(call);
+        return CallInvoker.AsyncServerStreamingCall(__Method_ListFeatures, null, options, request);
       }
-      public AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options)
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
+      public virtual AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
-        var call = CreateCall(__Method_RouteChat, options);
-        return Calls.AsyncDuplexStreamingCall(call);
+        return RecordRoute(new CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      ///  A client-to-server streaming RPC.
+      ///
+      ///  Accepts a stream of Points on a route being traversed, returning a
+      ///  RouteSummary when traversal is completed.
+      /// </summary>
+      public virtual AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options)
+      {
+        return CallInvoker.AsyncClientStreamingCall(__Method_RecordRoute, null, options);
+      }
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
+      public virtual AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        return RouteChat(new CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      ///  A Bidirectional streaming RPC.
+      ///
+      ///  Accepts a stream of RouteNotes sent while a route is being traversed,
+      ///  while receiving other RouteNotes (e.g. from other users).
+      /// </summary>
+      public virtual AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_RouteChat, null, options);
+      }
+      protected override RouteGuideClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new RouteGuideClient(configuration);
       }
     }
 
-    // creates service definition that can be registered with a server
+    /// <summary>Creates a new client for RouteGuide</summary>
+    public static RouteGuideClient NewClient(Channel channel)
+    {
+      return new RouteGuideClient(channel);
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    #pragma warning disable 0618
     public static ServerServiceDefinition BindService(IRouteGuide serviceImpl)
+    #pragma warning restore 0618
     {
       return ServerServiceDefinition.CreateBuilder(__ServiceName)
           .AddMethod(__Method_GetFeature, serviceImpl.GetFeature)
@@ -144,10 +420,16 @@
           .AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build();
     }
 
-    // creates a new client
-    public static RouteGuideClient NewClient(Channel channel)
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    #pragma warning disable 0618
+    public static ServerServiceDefinition BindService(RouteGuideBase serviceImpl)
+    #pragma warning restore 0618
     {
-      return new RouteGuideClient(channel);
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_GetFeature, serviceImpl.GetFeature)
+          .AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures)
+          .AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute)
+          .AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build();
     }
 
   }
diff --git a/examples/csharp/route_guide/RouteGuide/packages.config b/examples/csharp/route_guide/RouteGuide/packages.config
index c79aef1..b16bfed 100644
--- a/examples/csharp/route_guide/RouteGuide/packages.config
+++ b/examples/csharp/route_guide/RouteGuide/packages.config
@@ -1,9 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/route_guide/RouteGuideClient/Program.cs b/examples/csharp/route_guide/RouteGuideClient/Program.cs
index c561a9f..ee51fbe 100644
--- a/examples/csharp/route_guide/RouteGuideClient/Program.cs
+++ b/examples/csharp/route_guide/RouteGuideClient/Program.cs
@@ -43,9 +43,9 @@
         /// </summary>
         public class RouteGuideClient
         {
-            readonly RouteGuide.IRouteGuideClient client;
+            readonly RouteGuide.RouteGuideClient client;
 
-            public RouteGuideClient(RouteGuide.IRouteGuideClient client)
+            public RouteGuideClient(RouteGuide.RouteGuideClient client)
             {
                 this.client = client;
             }
diff --git a/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj b/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
index 3f7c4d0..c3700f6 100644
--- a/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
+++ b/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
@@ -11,7 +11,7 @@
     <AssemblyName>RouteGuideClient</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>2a1dd0a1</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>8ef088f0</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -37,9 +37,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -71,12 +71,12 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/examples/csharp/route_guide/RouteGuideClient/packages.config b/examples/csharp/route_guide/RouteGuideClient/packages.config
index c79aef1..b16bfed 100644
--- a/examples/csharp/route_guide/RouteGuideClient/packages.config
+++ b/examples/csharp/route_guide/RouteGuideClient/packages.config
@@ -1,9 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
index 20784fd..7a466e7 100644
--- a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
+++ b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
@@ -35,6 +35,7 @@
 using System.Text;
 using System.Threading.Tasks;
 
+using Grpc.Core;
 using Grpc.Core.Utils;
 
 namespace Routeguide
@@ -42,11 +43,11 @@
     /// <summary>
     /// Example implementation of RouteGuide server.
     /// </summary>
-    public class RouteGuideImpl : RouteGuide.IRouteGuide
+    public class RouteGuideImpl : RouteGuide.RouteGuideBase
     {
         readonly List<Feature> features;
         readonly object myLock = new object();
-        readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();   
+        readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<Point, List<RouteNote>>();
 
         public RouteGuideImpl(List<Feature> features)
         {
@@ -57,7 +58,7 @@
         /// Gets the feature at the requested point. If no feature at that location
         /// exists, an unnammed feature is returned at the provided location.
         /// </summary>
-        public Task<Feature> GetFeature(Point request, Grpc.Core.ServerCallContext context)
+        public override Task<Feature> GetFeature(Point request, ServerCallContext context)
         {
             return Task.FromResult(CheckFeature(request));
         }
@@ -65,7 +66,7 @@
         /// <summary>
         /// Gets all features contained within the given bounding rectangle.
         /// </summary>
-        public async Task ListFeatures(Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream, Grpc.Core.ServerCallContext context)
+        public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
         {
             var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
             foreach (var response in responses)
@@ -78,7 +79,7 @@
         /// Gets a stream of points, and responds with statistics about the "trip": number of points,
         /// number of known features visited, total distance traveled, and total time spent.
         /// </summary>
-        public async Task<RouteSummary> RecordRoute(Grpc.Core.IAsyncStreamReader<Point> requestStream, Grpc.Core.ServerCallContext context)
+        public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
         {
             int pointCount = 0;
             int featureCount = 0;
@@ -117,7 +118,7 @@
         /// Receives a stream of message/location pairs, and responds with a stream of all previous
         /// messages at each of those locations.
         /// </summary>
-        public async Task RouteChat(Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream, Grpc.Core.ServerCallContext context)
+        public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
         {
             while (await requestStream.MoveNext())
             {
diff --git a/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj b/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
index 599b12f..e7ecbc1 100644
--- a/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
+++ b/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
@@ -11,7 +11,7 @@
     <AssemblyName>RouteGuideServer</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>164e03eb</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>d5246467</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -37,9 +37,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
+    <Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
+      <HintPath>..\packages\Grpc.Core.0.14.0\lib\net45\Grpc.Core.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -72,12 +72,12 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
+  <Import Project="..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
+    <Error Condition="!Exists('..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.14.0\build\net45\Grpc.Core.targets'))" />
   </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/examples/csharp/route_guide/RouteGuideServer/packages.config b/examples/csharp/route_guide/RouteGuideServer/packages.config
index c79aef1..b16bfed 100644
--- a/examples/csharp/route_guide/RouteGuideServer/packages.config
+++ b/examples/csharp/route_guide/RouteGuideServer/packages.config
@@ -1,9 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
-  <package id="Grpc" version="0.13.1" targetFramework="net45" />
-  <package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
-  <package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
+  <package id="Grpc" version="0.14.0" targetFramework="net45" />
+  <package id="Grpc.Core" version="0.14.0" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/examples/csharp/route_guide/generate_protos.bat b/examples/csharp/route_guide/generate_protos.bat
index b3c5136..72c5ba3 100644
--- a/examples/csharp/route_guide/generate_protos.bat
+++ b/examples/csharp/route_guide/generate_protos.bat
@@ -34,7 +34,7 @@
 @rem enter this directory
 cd /d %~dp0
 
-set TOOLS_PATH=packages\Grpc.Tools.0.13.1\tools\windows_x86
+set TOOLS_PATH=packages\Grpc.Tools.0.14.0\tools\windows_x86
 
 %TOOLS_PATH%\protoc.exe -I../../protos --csharp_out RouteGuide  ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
 
diff --git a/gRPC.podspec b/gRPC.podspec
index a2d75be..6cf4a6f 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -181,7 +181,6 @@
                       'src/core/lib/iomgr/closure.h',
                       'src/core/lib/iomgr/endpoint.h',
                       'src/core/lib/iomgr/endpoint_pair.h',
-                      'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
                       'src/core/lib/iomgr/ev_poll_posix.h',
                       'src/core/lib/iomgr/ev_posix.h',
                       'src/core/lib/iomgr/exec_ctx.h',
@@ -260,15 +259,24 @@
                       'src/core/ext/transport/chttp2/transport/timeout_encoding.h',
                       'src/core/ext/transport/chttp2/transport/varint.h',
                       'src/core/ext/transport/chttp2/alpn/alpn.h',
-                      'src/core/lib/security/auth_filters.h',
-                      'src/core/lib/security/b64.h',
-                      'src/core/lib/security/credentials.h',
-                      'src/core/lib/security/handshake.h',
-                      'src/core/lib/security/json_token.h',
-                      'src/core/lib/security/jwt_verifier.h',
-                      'src/core/lib/security/secure_endpoint.h',
-                      'src/core/lib/security/security_connector.h',
-                      'src/core/lib/security/security_context.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/handshake.h',
+                      'src/core/lib/security/transport/secure_endpoint.h',
+                      'src/core/lib/security/transport/security_connector.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',
@@ -351,7 +359,6 @@
                       'src/core/lib/iomgr/endpoint.c',
                       'src/core/lib/iomgr/endpoint_pair_posix.c',
                       'src/core/lib/iomgr/endpoint_pair_windows.c',
-                      'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
                       'src/core/lib/iomgr/ev_poll_posix.c',
                       'src/core/lib/iomgr/ev_posix.c',
                       'src/core/lib/iomgr/exec_ctx.c',
@@ -441,20 +448,28 @@
                       '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/security/b64.c',
-                      'src/core/lib/security/client_auth_filter.c',
-                      'src/core/lib/security/credentials.c',
-                      'src/core/lib/security/credentials_metadata.c',
-                      'src/core/lib/security/credentials_posix.c',
-                      'src/core/lib/security/credentials_win32.c',
-                      'src/core/lib/security/google_default_credentials.c',
-                      'src/core/lib/security/handshake.c',
-                      'src/core/lib/security/json_token.c',
-                      'src/core/lib/security/jwt_verifier.c',
-                      'src/core/lib/security/secure_endpoint.c',
-                      'src/core/lib/security/security_connector.c',
-                      'src/core/lib/security/security_context.c',
-                      'src/core/lib/security/server_auth_filter.c',
+                      'src/core/lib/security/context/security_context.c',
+                      'src/core/lib/security/credentials/composite/composite_credentials.c',
+                      'src/core/lib/security/credentials/credentials.c',
+                      'src/core/lib/security/credentials/credentials_metadata.c',
+                      'src/core/lib/security/credentials/fake/fake_credentials.c',
+                      'src/core/lib/security/credentials/google_default/credentials_posix.c',
+                      'src/core/lib/security/credentials/google_default/credentials_win32.c',
+                      'src/core/lib/security/credentials/google_default/google_default_credentials.c',
+                      'src/core/lib/security/credentials/iam/iam_credentials.c',
+                      'src/core/lib/security/credentials/jwt/json_token.c',
+                      'src/core/lib/security/credentials/jwt/jwt_credentials.c',
+                      'src/core/lib/security/credentials/jwt/jwt_verifier.c',
+                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.c',
+                      'src/core/lib/security/credentials/plugin/plugin_credentials.c',
+                      'src/core/lib/security/credentials/ssl/ssl_credentials.c',
+                      'src/core/lib/security/transport/client_auth_filter.c',
+                      'src/core/lib/security/transport/handshake.c',
+                      'src/core/lib/security/transport/secure_endpoint.c',
+                      'src/core/lib/security/transport/security_connector.c',
+                      'src/core/lib/security/transport/server_auth_filter.c',
+                      'src/core/lib/security/util/b64.c',
+                      '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',
@@ -533,7 +548,6 @@
                               'src/core/lib/iomgr/closure.h',
                               'src/core/lib/iomgr/endpoint.h',
                               'src/core/lib/iomgr/endpoint_pair.h',
-                              'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
                               'src/core/lib/iomgr/ev_poll_posix.h',
                               'src/core/lib/iomgr/ev_posix.h',
                               'src/core/lib/iomgr/exec_ctx.h',
@@ -612,15 +626,24 @@
                               'src/core/ext/transport/chttp2/transport/timeout_encoding.h',
                               'src/core/ext/transport/chttp2/transport/varint.h',
                               'src/core/ext/transport/chttp2/alpn/alpn.h',
-                              'src/core/lib/security/auth_filters.h',
-                              'src/core/lib/security/b64.h',
-                              'src/core/lib/security/credentials.h',
-                              'src/core/lib/security/handshake.h',
-                              'src/core/lib/security/json_token.h',
-                              'src/core/lib/security/jwt_verifier.h',
-                              'src/core/lib/security/secure_endpoint.h',
-                              'src/core/lib/security/security_connector.h',
-                              'src/core/lib/security/security_context.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/handshake.h',
+                              'src/core/lib/security/transport/secure_endpoint.h',
+                              'src/core/lib/security/transport/security_connector.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',
diff --git a/grpc.def b/grpc.def
index 09a94a6..b811f0f 100644
--- a/grpc.def
+++ b/grpc.def
@@ -77,6 +77,7 @@
     grpc_server_request_registered_call
     grpc_server_create
     grpc_server_register_completion_queue
+    grpc_server_register_non_listening_completion_queue
     grpc_server_add_insecure_http2_port
     grpc_server_start
     grpc_server_shutdown_and_notify
diff --git a/grpc.gemspec b/grpc.gemspec
index dcac5cf..9dcd87c 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -190,7 +190,6 @@
   s.files += %w( src/core/lib/iomgr/closure.h )
   s.files += %w( src/core/lib/iomgr/endpoint.h )
   s.files += %w( src/core/lib/iomgr/endpoint_pair.h )
-  s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h )
   s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
   s.files += %w( src/core/lib/iomgr/ev_posix.h )
   s.files += %w( src/core/lib/iomgr/exec_ctx.h )
@@ -269,15 +268,24 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/timeout_encoding.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/varint.h )
   s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
-  s.files += %w( src/core/lib/security/auth_filters.h )
-  s.files += %w( src/core/lib/security/b64.h )
-  s.files += %w( src/core/lib/security/credentials.h )
-  s.files += %w( src/core/lib/security/handshake.h )
-  s.files += %w( src/core/lib/security/json_token.h )
-  s.files += %w( src/core/lib/security/jwt_verifier.h )
-  s.files += %w( src/core/lib/security/secure_endpoint.h )
-  s.files += %w( src/core/lib/security/security_connector.h )
-  s.files += %w( src/core/lib/security/security_context.h )
+  s.files += %w( src/core/lib/security/context/security_context.h )
+  s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/credentials.h )
+  s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/json_token.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.h )
+  s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
+  s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
+  s.files += %w( src/core/lib/security/transport/auth_filters.h )
+  s.files += %w( src/core/lib/security/transport/handshake.h )
+  s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
+  s.files += %w( src/core/lib/security/transport/security_connector.h )
+  s.files += %w( src/core/lib/security/util/b64.h )
+  s.files += %w( src/core/lib/security/util/json_util.h )
   s.files += %w( src/core/lib/tsi/fake_transport_security.h )
   s.files += %w( src/core/lib/tsi/ssl_transport_security.h )
   s.files += %w( src/core/lib/tsi/ssl_types.h )
@@ -330,7 +338,6 @@
   s.files += %w( src/core/lib/iomgr/endpoint.c )
   s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c )
   s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c )
-  s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c )
   s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )
   s.files += %w( src/core/lib/iomgr/ev_posix.c )
   s.files += %w( src/core/lib/iomgr/exec_ctx.c )
@@ -420,20 +427,28 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/writing.c )
   s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.c )
   s.files += %w( src/core/lib/http/httpcli_security_connector.c )
-  s.files += %w( src/core/lib/security/b64.c )
-  s.files += %w( src/core/lib/security/client_auth_filter.c )
-  s.files += %w( src/core/lib/security/credentials.c )
-  s.files += %w( src/core/lib/security/credentials_metadata.c )
-  s.files += %w( src/core/lib/security/credentials_posix.c )
-  s.files += %w( src/core/lib/security/credentials_win32.c )
-  s.files += %w( src/core/lib/security/google_default_credentials.c )
-  s.files += %w( src/core/lib/security/handshake.c )
-  s.files += %w( src/core/lib/security/json_token.c )
-  s.files += %w( src/core/lib/security/jwt_verifier.c )
-  s.files += %w( src/core/lib/security/secure_endpoint.c )
-  s.files += %w( src/core/lib/security/security_connector.c )
-  s.files += %w( src/core/lib/security/security_context.c )
-  s.files += %w( src/core/lib/security/server_auth_filter.c )
+  s.files += %w( src/core/lib/security/context/security_context.c )
+  s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/credentials.c )
+  s.files += %w( src/core/lib/security/credentials/credentials_metadata.c )
+  s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/google_default/credentials_posix.c )
+  s.files += %w( src/core/lib/security/credentials/google_default/credentials_win32.c )
+  s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/jwt/json_token.c )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.c )
+  s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c )
+  s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c )
+  s.files += %w( src/core/lib/security/transport/client_auth_filter.c )
+  s.files += %w( src/core/lib/security/transport/handshake.c )
+  s.files += %w( src/core/lib/security/transport/secure_endpoint.c )
+  s.files += %w( src/core/lib/security/transport/security_connector.c )
+  s.files += %w( src/core/lib/security/transport/server_auth_filter.c )
+  s.files += %w( src/core/lib/security/util/b64.c )
+  s.files += %w( src/core/lib/security/util/json_util.c )
   s.files += %w( src/core/lib/surface/init_secure.c )
   s.files += %w( src/core/lib/tsi/fake_transport_security.c )
   s.files += %w( src/core/lib/tsi/ssl_transport_security.c )
diff --git a/include/grpc++/impl/codegen/channel_interface.h b/include/grpc++/impl/codegen/channel_interface.h
index 6fcd5c3..cf78438 100644
--- a/include/grpc++/impl/codegen/channel_interface.h
+++ b/include/grpc++/impl/codegen/channel_interface.h
@@ -85,6 +85,16 @@
     return WaitForStateChangeImpl(last_observed, deadline_tp.raw_time());
   }
 
+  /// Wait for this channel to be connected
+  template <typename T>
+  bool WaitForConnected(T deadline) {
+    grpc_connectivity_state state;
+    while ((state = GetState(true)) != GRPC_CHANNEL_READY) {
+      if (!WaitForStateChange(state, deadline)) return false;
+    }
+    return true;
+  }
+
  private:
   template <class R>
   friend class ::grpc::ClientReader;
diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h
index 56864d6..1b84b44 100644
--- a/include/grpc++/impl/codegen/completion_queue.h
+++ b/include/grpc++/impl/codegen/completion_queue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -222,9 +222,18 @@
 /// A specific type of completion queue used by the processing of notifications
 /// by servers. Instantiated by \a ServerBuilder.
 class ServerCompletionQueue : public CompletionQueue {
+ public:
+  bool IsFrequentlyPolled() { return is_frequently_polled_; }
+
  private:
+  bool is_frequently_polled_;
   friend class ServerBuilder;
-  ServerCompletionQueue() {}
+  /// \param is_frequently_polled Informs the GPRC library about whether the
+  /// server completion queue would be actively polled (by calling Next() or
+  /// AsyncNext()). By default all server completion queues are assumed to be
+  /// frequently polled.
+  ServerCompletionQueue(bool is_frequently_polled = true)
+      : is_frequently_polled_(is_frequently_polled) {}
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index ad62952..8525cb7 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,7 +108,15 @@
   /// Add a completion queue for handling asynchronous services
   /// Caller is required to keep this completion queue live until
   /// the server is destroyed.
-  std::unique_ptr<ServerCompletionQueue> AddCompletionQueue();
+  ///
+  /// \param is_frequently_polled This is an optional parameter to inform GRPC
+  /// library about whether this completion queue would be frequently polled
+  /// (i.e by calling Next() or AsyncNext()). The default value is 'true' and is
+  /// the recommended setting. Setting this to 'false' (i.e not polling the
+  /// completion queue frequently) will have a significantly negative
+  /// performance impact and hence should not be used in production use cases.
+  std::unique_ptr<ServerCompletionQueue> AddCompletionQueue(
+      bool is_frequently_polled = true);
 
   /// Return a running server which is ready for processing calls.
   std::unique_ptr<Server> BuildAndStart();
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 0ca28c0..6f7a67b 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -334,6 +334,15 @@
                                                    grpc_completion_queue *cq,
                                                    void *reserved);
 
+/** Register a non-listening completion queue with the server. This API is
+    similar to grpc_server_register_completion_queue except that the server will
+    not use this completion_queue to listen to any incoming channels.
+
+    Registering a non-listening completion queue will have negative performance
+    impact and hence this API is not recommended for production use cases. */
+GRPCAPI void grpc_server_register_non_listening_completion_queue(
+    grpc_server *server, grpc_completion_queue *q, void *reserved);
+
 /** Add a HTTP2 over plaintext over tcp listener.
     Returns bound port number on success, 0 on failure.
     REQUIRES: server not started */
diff --git a/package.xml b/package.xml
index 04cf658..f9dd18c 100644
--- a/package.xml
+++ b/package.xml
@@ -10,7 +10,7 @@
   <email>grpc-packages@google.com</email>
   <active>yes</active>
  </lead>
- <date>2016-04-19</date>
+ <date>2016-05-19</date>
  <time>16:06:07</time>
  <version>
   <release>0.15.0</release>
@@ -22,7 +22,7 @@
  </stability>
  <license>BSD</license>
  <notes>
-- destroy grpc_byte_buffer after startBatch #6096
+- TBD
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
@@ -197,7 +197,6 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/closure.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
@@ -276,15 +275,24 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/timeout_encoding.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/auth_filters.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/b64.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/handshake.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/json_token.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/jwt_verifier.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/secure_endpoint.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/security_connector.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/security_context.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/context/security_context.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/fake/fake_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/google_default_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/iam/iam_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/json_token.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_verifier.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/handshake.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/b64.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/ssl_transport_security.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/ssl_types.h" role="src" />
@@ -337,7 +345,6 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.c" role="src" />
@@ -427,20 +434,28 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/writing.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/http/httpcli_security_connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/b64.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/client_auth_filter.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials_metadata.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/credentials_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/google_default_credentials.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/handshake.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/json_token.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/jwt_verifier.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/secure_endpoint.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/security_connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/security_context.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/server_auth_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/context/security_context.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/credentials_metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/fake/fake_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/credentials_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/credentials_win32.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/google_default/google_default_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/iam/iam_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/json_token.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/jwt/jwt_verifier.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/handshake.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/ssl_transport_security.c" role="src" />
@@ -1023,8 +1038,8 @@
   </release>
   <release>
    <version>
-    <release>0.15.0</release>
-    <api>0.15.0</api>
+    <release>0.14.0</release>
+    <api>0.14.0</api>
    </version>
    <stability>
     <release>beta</release>
@@ -1036,5 +1051,35 @@
 - destroy grpc_byte_buffer after startBatch #6096
    </notes>
   </release>
+  <release>
+   <version>
+    <release>0.14.2</release>
+    <api>0.14.2</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2016-05-18</date>
+   <license>BSD</license>
+   <notes>
+- Updated functions with TSRM macros for ZTS support #6607
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.15.0</release>
+    <api>0.15.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2016-05-19</date>
+   <license>BSD</license>
+   <notes>
+- TBD
+   </notes>
+  </release>
  </changelog>
 </package>
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index 08795d1..a67ec72 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -320,7 +320,7 @@
     c->filters = NULL;
   }
   c->addr = gpr_malloc(args->addr_len);
-  memcpy(c->addr, args->addr, args->addr_len);
+  if (args->addr_len) memcpy(c->addr, args->addr, args->addr_len);
   c->pollset_set = grpc_pollset_set_create();
   c->addr_len = args->addr_len;
   grpc_set_initial_connect_string(&c->addr, &c->addr_len,
diff --git a/src/core/ext/client_config/subchannel_index.c b/src/core/ext/client_config/subchannel_index.c
index ab8d9bd..690cb16 100644
--- a/src/core/ext/client_config/subchannel_index.c
+++ b/src/core/ext/client_config/subchannel_index.c
@@ -77,12 +77,19 @@
   grpc_subchannel_key *k = gpr_malloc(sizeof(*k));
   k->connector = grpc_connector_ref(connector);
   k->args.filter_count = args->filter_count;
-  k->args.filters = gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count);
-  memcpy((grpc_channel_filter *)k->args.filters, args->filters,
-         sizeof(*k->args.filters) * k->args.filter_count);
+  if (k->args.filter_count > 0) {
+    k->args.filters =
+        gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count);
+    memcpy((grpc_channel_filter *)k->args.filters, args->filters,
+           sizeof(*k->args.filters) * k->args.filter_count);
+  } else {
+    k->args.filters = NULL;
+  }
   k->args.addr_len = args->addr_len;
   k->args.addr = gpr_malloc(args->addr_len);
-  memcpy(k->args.addr, args->addr, k->args.addr_len);
+  if (k->args.addr_len > 0) {
+    memcpy(k->args.addr, args->addr, k->args.addr_len);
+  }
   k->args.args = copy_channel_args(args->args);
   return k;
 }
@@ -104,11 +111,15 @@
   if (c != 0) return c;
   c = GPR_ICMP(a->args.filter_count, b->args.filter_count);
   if (c != 0) return c;
-  c = memcmp(a->args.addr, b->args.addr, a->args.addr_len);
-  if (c != 0) return c;
-  c = memcmp(a->args.filters, b->args.filters,
-             a->args.filter_count * sizeof(*a->args.filters));
-  if (c != 0) return c;
+  if (a->args.addr_len) {
+    c = memcmp(a->args.addr, b->args.addr, a->args.addr_len);
+    if (c != 0) return c;
+  }
+  if (a->args.filter_count > 0) {
+    c = memcmp(a->args.filters, b->args.filters,
+               a->args.filter_count * sizeof(*a->args.filters));
+    if (c != 0) return c;
+  }
   return grpc_channel_args_compare(a->args.args, b->args.args);
 }
 
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 58af6f9..a262306 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
@@ -45,9 +45,9 @@
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/tcp_client.h"
-#include "src/core/lib/security/auth_filters.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/auth_filters.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/tsi/transport_security_interface.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 e21fa2a..0428bb1 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -43,14 +43,8 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-static void setup_transport(grpc_exec_ctx *exec_ctx, void *server,
-                            grpc_transport *transport) {
-  grpc_server_setup_transport(exec_ctx, server, transport,
-                              grpc_server_get_channel_args(server));
-}
-
 static void new_transport(grpc_exec_ctx *exec_ctx, void *server,
-                          grpc_endpoint *tcp,
+                          grpc_endpoint *tcp, grpc_pollset *accepting_pollset,
                           grpc_tcp_server_acceptor *acceptor) {
   /*
    * Beware that the call to grpc_create_chttp2_transport() has to happen before
@@ -61,7 +55,8 @@
    */
   grpc_transport *transport = grpc_create_chttp2_transport(
       exec_ctx, grpc_server_get_channel_args(server), tcp, 0);
-  setup_transport(exec_ctx, server, transport);
+  grpc_server_setup_transport(exec_ctx, server, transport, accepting_pollset,
+                              grpc_server_get_channel_args(server));
   grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
 }
 
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 698b2be..ebbefbc 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
@@ -45,14 +45,14 @@
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/tcp_server.h"
-#include "src/core/lib/security/auth_filters.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/security_connector.h"
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/auth_filters.h"
+#include "src/core/lib/security/transport/security_connector.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-typedef struct grpc_server_secure_state {
+typedef struct server_secure_state {
   grpc_server *server;
   grpc_tcp_server *tcp;
   grpc_server_security_connector *sc;
@@ -62,13 +62,16 @@
   gpr_refcount refcount;
   grpc_closure destroy_closure;
   grpc_closure *destroy_callback;
-} grpc_server_secure_state;
+} server_secure_state;
 
-static void state_ref(grpc_server_secure_state *state) {
-  gpr_ref(&state->refcount);
-}
+typedef struct server_secure_connect {
+  server_secure_state *state;
+  grpc_pollset *accepting_pollset;
+} server_secure_connect;
 
-static void state_unref(grpc_server_secure_state *state) {
+static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); }
+
+static void state_unref(server_secure_state *state) {
   if (gpr_unref(&state->refcount)) {
     /* ensure all threads have unlocked */
     gpr_mu_lock(&state->mu);
@@ -80,67 +83,66 @@
   }
 }
 
-static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
-                            grpc_transport *transport,
-                            grpc_auth_context *auth_context) {
-  grpc_server_secure_state *state = statep;
-  grpc_channel_args *args_copy;
-  grpc_arg args_to_add[2];
-  args_to_add[0] = grpc_server_credentials_to_arg(state->creds);
-  args_to_add[1] = grpc_auth_context_to_arg(auth_context);
-  args_copy = grpc_channel_args_copy_and_add(
-      grpc_server_get_channel_args(state->server), args_to_add,
-      GPR_ARRAY_SIZE(args_to_add));
-  grpc_server_setup_transport(exec_ctx, state->server, transport, args_copy);
-  grpc_channel_args_destroy(args_copy);
-}
-
 static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
                                      grpc_security_status status,
                                      grpc_endpoint *secure_endpoint,
                                      grpc_auth_context *auth_context) {
-  grpc_server_secure_state *state = statep;
+  server_secure_connect *state = statep;
   grpc_transport *transport;
   if (status == GRPC_SECURITY_OK) {
     if (secure_endpoint) {
-      gpr_mu_lock(&state->mu);
-      if (!state->is_shutdown) {
+      gpr_mu_lock(&state->state->mu);
+      if (!state->state->is_shutdown) {
         transport = grpc_create_chttp2_transport(
-            exec_ctx, grpc_server_get_channel_args(state->server),
+            exec_ctx, grpc_server_get_channel_args(state->state->server),
             secure_endpoint, 0);
-        setup_transport(exec_ctx, state, transport, auth_context);
+        grpc_channel_args *args_copy;
+        grpc_arg args_to_add[2];
+        args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds);
+        args_to_add[1] = grpc_auth_context_to_arg(auth_context);
+        args_copy = grpc_channel_args_copy_and_add(
+            grpc_server_get_channel_args(state->state->server), args_to_add,
+            GPR_ARRAY_SIZE(args_to_add));
+        grpc_server_setup_transport(exec_ctx, state->state->server, transport,
+                                    state->accepting_pollset, args_copy);
+        grpc_channel_args_destroy(args_copy);
         grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
       } else {
         /* We need to consume this here, because the server may already have
          * gone away. */
         grpc_endpoint_destroy(exec_ctx, secure_endpoint);
       }
-      gpr_mu_unlock(&state->mu);
+      gpr_mu_unlock(&state->state->mu);
     }
   } else {
     gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
   }
-  state_unref(state);
+  state_unref(state->state);
+  gpr_free(state);
 }
 
 static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
+                      grpc_pollset *accepting_pollset,
                       grpc_tcp_server_acceptor *acceptor) {
-  grpc_server_secure_state *state = statep;
-  state_ref(state);
-  grpc_server_security_connector_do_handshake(
-      exec_ctx, state->sc, acceptor, tcp, on_secure_handshake_done, state);
+  server_secure_connect *state = gpr_malloc(sizeof(*state));
+  state->state = statep;
+  state_ref(state->state);
+  state->accepting_pollset = accepting_pollset;
+  grpc_server_security_connector_do_handshake(exec_ctx, state->state->sc,
+                                              acceptor, tcp,
+                                              on_secure_handshake_done, state);
 }
 
 /* Server callback: start listening on our ports */
 static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
                   grpc_pollset **pollsets, size_t pollset_count) {
-  grpc_server_secure_state *state = statep;
+  server_secure_state *state = statep;
   grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count,
                         on_accept, state);
 }
 
 static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) {
-  grpc_server_secure_state *state = statep;
+  server_secure_state *state = statep;
   if (state->destroy_callback != NULL) {
     state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
                                 success);
@@ -153,7 +155,7 @@
    callbacks) */
 static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
                     grpc_closure *callback) {
-  grpc_server_secure_state *state = statep;
+  server_secure_state *state = statep;
   grpc_tcp_server *tcp;
   gpr_mu_lock(&state->mu);
   state->is_shutdown = 1;
@@ -167,7 +169,7 @@
                                       grpc_server_credentials *creds) {
   grpc_resolved_addresses *resolved = NULL;
   grpc_tcp_server *tcp = NULL;
-  grpc_server_secure_state *state = NULL;
+  server_secure_state *state = NULL;
   size_t i;
   unsigned count = 0;
   int port_num = -1;
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.c b/src/core/ext/transport/chttp2/transport/frame_goaway.c
index 69accb7..827e7a6 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.c
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.c
@@ -137,7 +137,8 @@
       ++cur;
     /* fallthrough */
     case GRPC_CHTTP2_GOAWAY_DEBUG:
-      memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur));
+      if (end != cur)
+        memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur));
       GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos);
       p->debug_pos += (uint32_t)(end - cur);
       p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index 687936b..ed45bc9 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -1138,6 +1138,7 @@
 /* append some bytes to a string */
 static void append_bytes(grpc_chttp2_hpack_parser_string *str,
                          const uint8_t *data, size_t length) {
+  if (length == 0) return;
   if (length + str->length > str->capacity) {
     GPR_ASSERT(str->length + length <= UINT32_MAX);
     str->capacity = (uint32_t)(str->length + length);
@@ -1445,6 +1446,11 @@
        stream id on a header */
     if (stream_parsing != NULL) {
       if (parser->is_boundary) {
+        if (stream_parsing->header_frames_received ==
+            GPR_ARRAY_SIZE(stream_parsing->got_metadata_on_parse)) {
+          gpr_log(GPR_ERROR, "too many trailer frames");
+          return GRPC_CHTTP2_CONNECTION_ERROR;
+        }
         stream_parsing
             ->got_metadata_on_parse[stream_parsing->header_frames_received] = 1;
         stream_parsing->header_frames_received++;
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index bebc644..1bb53b7 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -222,8 +222,11 @@
 static void process_recv_message(stream_obj *s, const uint8_t *recv_data) {
   gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes);
   uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
-  memcpy(dst_p, recv_data, (size_t)s->total_read_bytes);
-  gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice);
+  if (s->total_read_bytes > 0) {
+    // Only copy if there is non-zero number of bytes
+    memcpy(dst_p, recv_data, (size_t)s->total_read_bytes);
+    gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice);
+  }
   grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0);
   *s->recv_message = (grpc_byte_buffer *)&s->sbs;
 }
@@ -351,8 +354,17 @@
           if (grpc_cronet_trace) {
             gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
           }
-          cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer,
-                                           s->remaining_read_bytes);
+          if (s->remaining_read_bytes > 0) {
+            cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer,
+                                             s->remaining_read_bytes);
+          } else {
+            // Calling the closing callback directly since this is a 0 byte read
+            // for an empty message.
+            process_recv_message(s, NULL);
+            enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
+            invoke_closing_callback(s);
+            set_recv_state(s, CRONET_RECV_CLOSED);
+          }
         }
       }
       break;
diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c
index 893cf07..569be4d 100644
--- a/src/core/lib/channel/channel_args.c
+++ b/src/core/lib/channel/channel_args.c
@@ -132,7 +132,8 @@
   for (size_t i = 0; i < a->num_args; i++) {
     args[i] = &a->args[i];
   }
-  qsort(args, a->num_args, sizeof(grpc_arg *), cmp_key_stable);
+  if (a->num_args > 1)
+    qsort(args, a->num_args, sizeof(grpc_arg *), cmp_key_stable);
 
   grpc_channel_args *b = gpr_malloc(sizeof(grpc_channel_args));
   b->num_args = a->num_args;
diff --git a/src/core/lib/compression/compression_algorithm.c b/src/core/lib/compression/compression_algorithm.c
index 7039364..820871d 100644
--- a/src/core/lib/compression/compression_algorithm.c
+++ b/src/core/lib/compression/compression_algorithm.c
@@ -199,5 +199,6 @@
 int grpc_compression_options_is_algorithm_enabled(
     const grpc_compression_options *opts,
     grpc_compression_algorithm algorithm) {
+  if (algorithm >= GRPC_COMPRESS_ALGORITHMS_COUNT) return 0;
   return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
 }
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index ea4bff3..5590928 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -38,7 +38,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
-#include "src/core/lib/security/handshake.h"
+#include "src/core/lib/security/transport/handshake.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/tsi/ssl_transport_security.h"
 
diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
deleted file mode 100644
index aeb6e28..0000000
--- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
+++ /dev/null
@@ -1,1934 +0,0 @@
-/*
- *
- * Copyright 2015, 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.
- *
- */
-
-/* This file will be removed shortly: it's here to keep refactoring
- * steps simple and auditable.
- * It's the combination of the old files:
- *  - fd_posix.{h,c}
- *  - pollset_posix.{h,c}
- *  - pullset_multipoller_with_{poll,epoll}.{h,c}
- * The new version will be split into:
- *  - ev_poll_posix.{h,c}
- *  - ev_epoll_posix.{h,c}
- */
-
-#include <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_SOCKET
-
-#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <poll.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/tls.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/lib/iomgr/iomgr_internal.h"
-#include "src/core/lib/iomgr/wakeup_fd_posix.h"
-#include "src/core/lib/profiling/timers.h"
-#include "src/core/lib/support/block_annotate.h"
-
-/*******************************************************************************
- * FD declarations
- */
-
-typedef struct grpc_fd_watcher {
-  struct grpc_fd_watcher *next;
-  struct grpc_fd_watcher *prev;
-  grpc_pollset *pollset;
-  grpc_pollset_worker *worker;
-  grpc_fd *fd;
-} grpc_fd_watcher;
-
-struct grpc_fd {
-  int fd;
-  /* refst format:
-     bit0:   1=active/0=orphaned
-     bit1-n: refcount
-     meaning that mostly we ref by two to avoid altering the orphaned bit,
-     and just unref by 1 when we're ready to flag the object as orphaned */
-  gpr_atm refst;
-
-  gpr_mu mu;
-  int shutdown;
-  int closed;
-  int released;
-
-  /* The watcher list.
-
-     The following watcher related fields are protected by watcher_mu.
-
-     An fd_watcher is an ephemeral object created when an fd wants to
-     begin polling, and destroyed after the poll.
-
-     It denotes the fd's interest in whether to read poll or write poll
-     or both or neither on this fd.
-
-     If a watcher is asked to poll for reads or writes, the read_watcher
-     or write_watcher fields are set respectively. A watcher may be asked
-     to poll for both, in which case both fields will be set.
-
-     read_watcher and write_watcher may be NULL if no watcher has been
-     asked to poll for reads or writes.
-
-     If an fd_watcher is not asked to poll for reads or writes, it's added
-     to a linked list of inactive watchers, rooted at inactive_watcher_root.
-     If at a later time there becomes need of a poller to poll, one of
-     the inactive pollers may be kicked out of their poll loops to take
-     that responsibility. */
-  grpc_fd_watcher inactive_watcher_root;
-  grpc_fd_watcher *read_watcher;
-  grpc_fd_watcher *write_watcher;
-
-  grpc_closure *read_closure;
-  grpc_closure *write_closure;
-
-  struct grpc_fd *freelist_next;
-
-  grpc_closure *on_done_closure;
-
-  grpc_iomgr_object iomgr_object;
-};
-
-/* Begin polling on an fd.
-   Registers that the given pollset is interested in this fd - so that if read
-   or writability interest changes, the pollset can be kicked to pick up that
-   new interest.
-   Return value is:
-     (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0)
-   i.e. a combination of read_mask and write_mask determined by the fd's current
-   interest in said events.
-   Polling strategies that do not need to alter their behavior depending on the
-   fd's current interest (such as epoll) do not need to call this function.
-   MUST NOT be called with a pollset lock taken */
-static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
-                              grpc_pollset_worker *worker, uint32_t read_mask,
-                              uint32_t write_mask, grpc_fd_watcher *rec);
-/* Complete polling previously started with fd_begin_poll
-   MUST NOT be called with a pollset lock taken
-   if got_read or got_write are 1, also does the become_{readable,writable} as
-   appropriate. */
-static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
-                        int got_read, int got_write);
-
-/* Return 1 if this fd is orphaned, 0 otherwise */
-static bool fd_is_orphaned(grpc_fd *fd);
-
-/* Reference counting for fds */
-/*#define GRPC_FD_REF_COUNT_DEBUG*/
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
-static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
-                     int line);
-#define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__)
-#define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__)
-#else
-static void fd_ref(grpc_fd *fd);
-static void fd_unref(grpc_fd *fd);
-#define GRPC_FD_REF(fd, reason) fd_ref(fd)
-#define GRPC_FD_UNREF(fd, reason) fd_unref(fd)
-#endif
-
-static void fd_global_init(void);
-static void fd_global_shutdown(void);
-
-#define CLOSURE_NOT_READY ((grpc_closure *)0)
-#define CLOSURE_READY ((grpc_closure *)1)
-
-/*******************************************************************************
- * pollset declarations
- */
-
-typedef struct grpc_pollset_vtable grpc_pollset_vtable;
-
-typedef struct grpc_cached_wakeup_fd {
-  grpc_wakeup_fd fd;
-  struct grpc_cached_wakeup_fd *next;
-} grpc_cached_wakeup_fd;
-
-struct grpc_pollset_worker {
-  grpc_cached_wakeup_fd *wakeup_fd;
-  int reevaluate_polling_on_wakeup;
-  int kicked_specifically;
-  struct grpc_pollset_worker *next;
-  struct grpc_pollset_worker *prev;
-};
-
-struct grpc_pollset {
-  /* pollsets under posix can mutate representation as fds are added and
-     removed.
-     For example, we may choose a poll() based implementation on linux for
-     few fds, and an epoll() based implementation for many fds */
-  const grpc_pollset_vtable *vtable;
-  gpr_mu mu;
-  grpc_pollset_worker root_worker;
-  int in_flight_cbs;
-  int shutting_down;
-  int called_shutdown;
-  int kicked_without_pollers;
-  grpc_closure *shutdown_done;
-  grpc_closure_list idle_jobs;
-  union {
-    int fd;
-    void *ptr;
-  } data;
-  /* Local cache of eventfds for workers */
-  grpc_cached_wakeup_fd *local_wakeup_cache;
-};
-
-struct grpc_pollset_vtable {
-  void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                 struct grpc_fd *fd, int and_unlock_pollset);
-  void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                                grpc_pollset_worker *worker,
-                                gpr_timespec deadline, gpr_timespec now);
-  void (*finish_shutdown)(grpc_pollset *pollset);
-  void (*destroy)(grpc_pollset *pollset);
-};
-
-/* Add an fd to a pollset */
-static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           struct grpc_fd *fd);
-
-static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
-                               grpc_pollset_set *pollset_set, grpc_fd *fd);
-
-/* Convert a timespec to milliseconds:
-   - very small or negative poll times are clamped to zero to do a
-     non-blocking poll (which becomes spin polling)
-   - other small values are rounded up to one millisecond
-   - longer than a millisecond polls are rounded up to the next nearest
-     millisecond to avoid spinning
-   - infinite timeouts are converted to -1 */
-static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
-                                           gpr_timespec now);
-
-/* Allow kick to wakeup the currently polling worker */
-#define GRPC_POLLSET_CAN_KICK_SELF 1
-/* Force the wakee to repoll when awoken */
-#define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2
-/* As per pollset_kick, with an extended set of flags (defined above)
-   -- mostly for fd_posix's use. */
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags);
-
-/* turn a pollset into a multipoller: platform specific */
-typedef void (*platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx,
-                                                 grpc_pollset *pollset,
-                                                 struct grpc_fd **fds,
-                                                 size_t fd_count);
-static platform_become_multipoller_type platform_become_multipoller;
-
-/* Return 1 if the pollset has active threads in pollset_work (pollset must
- * be locked) */
-static int pollset_has_workers(grpc_pollset *pollset);
-
-static void remove_fd_from_all_epoll_sets(int fd);
-
-/*******************************************************************************
- * pollset_set definitions
- */
-
-struct grpc_pollset_set {
-  gpr_mu mu;
-
-  size_t pollset_count;
-  size_t pollset_capacity;
-  grpc_pollset **pollsets;
-
-  size_t pollset_set_count;
-  size_t pollset_set_capacity;
-  struct grpc_pollset_set **pollset_sets;
-
-  size_t fd_count;
-  size_t fd_capacity;
-  grpc_fd **fds;
-};
-
-/*******************************************************************************
- * fd_posix.c
- */
-
-/* We need to keep a freelist not because of any concerns of malloc performance
- * but instead so that implementations with multiple threads in (for example)
- * epoll_wait deal with the race between pollset removal and incoming poll
- * notifications.
- *
- * The problem is that the poller ultimately holds a reference to this
- * object, so it is very difficult to know when is safe to free it, at least
- * without some expensive synchronization.
- *
- * If we keep the object freelisted, in the worst case losing this race just
- * becomes a spurious read notification on a reused fd.
- */
-/* TODO(klempner): We could use some form of polling generation count to know
- * when these are safe to free. */
-/* TODO(klempner): Consider disabling freelisting if we don't have multiple
- * threads in poll on the same fd */
-/* TODO(klempner): Batch these allocations to reduce fragmentation */
-static grpc_fd *fd_freelist = NULL;
-static gpr_mu fd_freelist_mu;
-
-static void freelist_fd(grpc_fd *fd) {
-  gpr_mu_lock(&fd_freelist_mu);
-  fd->freelist_next = fd_freelist;
-  fd_freelist = fd;
-  grpc_iomgr_unregister_object(&fd->iomgr_object);
-  gpr_mu_unlock(&fd_freelist_mu);
-}
-
-static grpc_fd *alloc_fd(int fd) {
-  grpc_fd *r = NULL;
-  gpr_mu_lock(&fd_freelist_mu);
-  if (fd_freelist != NULL) {
-    r = fd_freelist;
-    fd_freelist = fd_freelist->freelist_next;
-  }
-  gpr_mu_unlock(&fd_freelist_mu);
-  if (r == NULL) {
-    r = gpr_malloc(sizeof(grpc_fd));
-    gpr_mu_init(&r->mu);
-  }
-
-  gpr_mu_lock(&r->mu);
-  gpr_atm_rel_store(&r->refst, 1);
-  r->shutdown = 0;
-  r->read_closure = CLOSURE_NOT_READY;
-  r->write_closure = CLOSURE_NOT_READY;
-  r->fd = fd;
-  r->inactive_watcher_root.next = r->inactive_watcher_root.prev =
-      &r->inactive_watcher_root;
-  r->freelist_next = NULL;
-  r->read_watcher = r->write_watcher = NULL;
-  r->on_done_closure = NULL;
-  r->closed = 0;
-  r->released = 0;
-  gpr_mu_unlock(&r->mu);
-  return r;
-}
-
-static void destroy(grpc_fd *fd) {
-  gpr_mu_destroy(&fd->mu);
-  gpr_free(fd);
-}
-
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
-#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
-static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
-                   int line) {
-  gpr_log(GPR_DEBUG, "FD %d %p   ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
-          gpr_atm_no_barrier_load(&fd->refst),
-          gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
-#else
-#define REF_BY(fd, n, reason) ref_by(fd, n)
-#define UNREF_BY(fd, n, reason) unref_by(fd, n)
-static void ref_by(grpc_fd *fd, int n) {
-#endif
-  GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
-}
-
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
-                     int line) {
-  gpr_atm old;
-  gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
-          gpr_atm_no_barrier_load(&fd->refst),
-          gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
-#else
-static void unref_by(grpc_fd *fd, int n) {
-  gpr_atm old;
-#endif
-  old = gpr_atm_full_fetch_add(&fd->refst, -n);
-  if (old == n) {
-    freelist_fd(fd);
-  } else {
-    GPR_ASSERT(old > n);
-  }
-}
-
-static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
-
-static void fd_global_shutdown(void) {
-  gpr_mu_lock(&fd_freelist_mu);
-  gpr_mu_unlock(&fd_freelist_mu);
-  while (fd_freelist != NULL) {
-    grpc_fd *fd = fd_freelist;
-    fd_freelist = fd_freelist->freelist_next;
-    destroy(fd);
-  }
-  gpr_mu_destroy(&fd_freelist_mu);
-}
-
-static grpc_fd *fd_create(int fd, const char *name) {
-  grpc_fd *r = alloc_fd(fd);
-  char *name2;
-  gpr_asprintf(&name2, "%s fd=%d", name, fd);
-  grpc_iomgr_register_object(&r->iomgr_object, name2);
-  gpr_free(name2);
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-  gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name);
-#endif
-  return r;
-}
-
-static bool fd_is_orphaned(grpc_fd *fd) {
-  return (gpr_atm_acq_load(&fd->refst) & 1) == 0;
-}
-
-static void pollset_kick_locked(grpc_fd_watcher *watcher) {
-  gpr_mu_lock(&watcher->pollset->mu);
-  GPR_ASSERT(watcher->worker);
-  pollset_kick_ext(watcher->pollset, watcher->worker,
-                   GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
-  gpr_mu_unlock(&watcher->pollset->mu);
-}
-
-static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
-  if (fd->inactive_watcher_root.next != &fd->inactive_watcher_root) {
-    pollset_kick_locked(fd->inactive_watcher_root.next);
-  } else if (fd->read_watcher) {
-    pollset_kick_locked(fd->read_watcher);
-  } else if (fd->write_watcher) {
-    pollset_kick_locked(fd->write_watcher);
-  }
-}
-
-static void wake_all_watchers_locked(grpc_fd *fd) {
-  grpc_fd_watcher *watcher;
-  for (watcher = fd->inactive_watcher_root.next;
-       watcher != &fd->inactive_watcher_root; watcher = watcher->next) {
-    pollset_kick_locked(watcher);
-  }
-  if (fd->read_watcher) {
-    pollset_kick_locked(fd->read_watcher);
-  }
-  if (fd->write_watcher && fd->write_watcher != fd->read_watcher) {
-    pollset_kick_locked(fd->write_watcher);
-  }
-}
-
-static int has_watchers(grpc_fd *fd) {
-  return fd->read_watcher != NULL || fd->write_watcher != NULL ||
-         fd->inactive_watcher_root.next != &fd->inactive_watcher_root;
-}
-
-static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  fd->closed = 1;
-  if (!fd->released) {
-    close(fd->fd);
-  } else {
-    remove_fd_from_all_epoll_sets(fd->fd);
-  }
-  grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
-}
-
-static int fd_wrapped_fd(grpc_fd *fd) {
-  if (fd->released || fd->closed) {
-    return -1;
-  } else {
-    return fd->fd;
-  }
-}
-
-static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                      grpc_closure *on_done, int *release_fd,
-                      const char *reason) {
-  fd->on_done_closure = on_done;
-  fd->released = release_fd != NULL;
-  if (!fd->released) {
-    shutdown(fd->fd, SHUT_RDWR);
-  } else {
-    *release_fd = fd->fd;
-  }
-  gpr_mu_lock(&fd->mu);
-  REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
-  if (!has_watchers(fd)) {
-    close_fd_locked(exec_ctx, fd);
-  } else {
-    wake_all_watchers_locked(fd);
-  }
-  gpr_mu_unlock(&fd->mu);
-  UNREF_BY(fd, 2, reason); /* drop the reference */
-}
-
-/* increment refcount by two to avoid changing the orphan bit */
-#ifdef GRPC_FD_REF_COUNT_DEBUG
-static void fd_ref(grpc_fd *fd, const char *reason, const char *file,
-                   int line) {
-  ref_by(fd, 2, reason, file, line);
-}
-
-static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
-                     int line) {
-  unref_by(fd, 2, reason, file, line);
-}
-#else
-static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
-
-static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
-#endif
-
-static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                             grpc_closure **st, grpc_closure *closure) {
-  if (*st == CLOSURE_NOT_READY) {
-    /* not ready ==> switch to a waiting state by setting the closure */
-    *st = closure;
-  } else if (*st == CLOSURE_READY) {
-    /* already ready ==> queue the closure to run immediately */
-    *st = CLOSURE_NOT_READY;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL);
-    maybe_wake_one_watcher_locked(fd);
-  } else {
-    /* upcallptr was set to a different closure.  This is an error! */
-    gpr_log(GPR_ERROR,
-            "User called a notify_on function with a previous callback still "
-            "pending");
-    abort();
-  }
-}
-
-/* returns 1 if state becomes not ready */
-static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                            grpc_closure **st) {
-  if (*st == CLOSURE_READY) {
-    /* duplicate ready ==> ignore */
-    return 0;
-  } else if (*st == CLOSURE_NOT_READY) {
-    /* not ready, and not waiting ==> flag ready */
-    *st = CLOSURE_READY;
-    return 0;
-  } else {
-    /* waiting ==> queue closure */
-    grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL);
-    *st = CLOSURE_NOT_READY;
-    return 1;
-  }
-}
-
-static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  gpr_mu_lock(&fd->mu);
-  GPR_ASSERT(!fd->shutdown);
-  fd->shutdown = 1;
-  set_ready_locked(exec_ctx, fd, &fd->read_closure);
-  set_ready_locked(exec_ctx, fd, &fd->write_closure);
-  gpr_mu_unlock(&fd->mu);
-}
-
-static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                              grpc_closure *closure) {
-  gpr_mu_lock(&fd->mu);
-  notify_on_locked(exec_ctx, fd, &fd->read_closure, closure);
-  gpr_mu_unlock(&fd->mu);
-}
-
-static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                               grpc_closure *closure) {
-  gpr_mu_lock(&fd->mu);
-  notify_on_locked(exec_ctx, fd, &fd->write_closure, closure);
-  gpr_mu_unlock(&fd->mu);
-}
-
-static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
-                              grpc_pollset_worker *worker, uint32_t read_mask,
-                              uint32_t write_mask, grpc_fd_watcher *watcher) {
-  uint32_t mask = 0;
-  grpc_closure *cur;
-  int requested;
-  /* keep track of pollers that have requested our events, in case they change
-   */
-  GRPC_FD_REF(fd, "poll");
-
-  gpr_mu_lock(&fd->mu);
-
-  /* if we are shutdown, then don't add to the watcher set */
-  if (fd->shutdown) {
-    watcher->fd = NULL;
-    watcher->pollset = NULL;
-    watcher->worker = NULL;
-    gpr_mu_unlock(&fd->mu);
-    GRPC_FD_UNREF(fd, "poll");
-    return 0;
-  }
-
-  /* if there is nobody polling for read, but we need to, then start doing so */
-  cur = fd->read_closure;
-  requested = cur != CLOSURE_READY;
-  if (read_mask && fd->read_watcher == NULL && requested) {
-    fd->read_watcher = watcher;
-    mask |= read_mask;
-  }
-  /* if there is nobody polling for write, but we need to, then start doing so
-   */
-  cur = fd->write_closure;
-  requested = cur != CLOSURE_READY;
-  if (write_mask && fd->write_watcher == NULL && requested) {
-    fd->write_watcher = watcher;
-    mask |= write_mask;
-  }
-  /* if not polling, remember this watcher in case we need someone to later */
-  if (mask == 0 && worker != NULL) {
-    watcher->next = &fd->inactive_watcher_root;
-    watcher->prev = watcher->next->prev;
-    watcher->next->prev = watcher->prev->next = watcher;
-  }
-  watcher->pollset = pollset;
-  watcher->worker = worker;
-  watcher->fd = fd;
-  gpr_mu_unlock(&fd->mu);
-
-  return mask;
-}
-
-static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher,
-                        int got_read, int got_write) {
-  int was_polling = 0;
-  int kick = 0;
-  grpc_fd *fd = watcher->fd;
-
-  if (fd == NULL) {
-    return;
-  }
-
-  gpr_mu_lock(&fd->mu);
-
-  if (watcher == fd->read_watcher) {
-    /* remove read watcher, kick if we still need a read */
-    was_polling = 1;
-    if (!got_read) {
-      kick = 1;
-    }
-    fd->read_watcher = NULL;
-  }
-  if (watcher == fd->write_watcher) {
-    /* remove write watcher, kick if we still need a write */
-    was_polling = 1;
-    if (!got_write) {
-      kick = 1;
-    }
-    fd->write_watcher = NULL;
-  }
-  if (!was_polling && watcher->worker != NULL) {
-    /* remove from inactive list */
-    watcher->next->prev = watcher->prev;
-    watcher->prev->next = watcher->next;
-  }
-  if (got_read) {
-    if (set_ready_locked(exec_ctx, fd, &fd->read_closure)) {
-      kick = 1;
-    }
-  }
-  if (got_write) {
-    if (set_ready_locked(exec_ctx, fd, &fd->write_closure)) {
-      kick = 1;
-    }
-  }
-  if (kick) {
-    maybe_wake_one_watcher_locked(fd);
-  }
-  if (fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
-    close_fd_locked(exec_ctx, fd);
-  }
-  gpr_mu_unlock(&fd->mu);
-
-  GRPC_FD_UNREF(fd, "poll");
-}
-
-/*******************************************************************************
- * pollset_posix.c
- */
-
-GPR_TLS_DECL(g_current_thread_poller);
-GPR_TLS_DECL(g_current_thread_worker);
-
-/** The alarm system needs to be able to wakeup 'some poller' sometimes
- *  (specifically when a new alarm needs to be triggered earlier than the next
- *  alarm 'epoch').
- *  This wakeup_fd gives us something to alert on when such a case occurs. */
-grpc_wakeup_fd grpc_global_wakeup_fd;
-
-static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
-  worker->prev->next = worker->next;
-  worker->next->prev = worker->prev;
-}
-
-static int pollset_has_workers(grpc_pollset *p) {
-  return p->root_worker.next != &p->root_worker;
-}
-
-static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) {
-  if (pollset_has_workers(p)) {
-    grpc_pollset_worker *w = p->root_worker.next;
-    remove_worker(p, w);
-    return w;
-  } else {
-    return NULL;
-  }
-}
-
-static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
-  worker->next = &p->root_worker;
-  worker->prev = worker->next->prev;
-  worker->prev->next = worker->next->prev = worker;
-}
-
-static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
-  worker->prev = &p->root_worker;
-  worker->next = worker->prev->next;
-  worker->prev->next = worker->next->prev = worker;
-}
-
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags) {
-  GPR_TIMER_BEGIN("pollset_kick_ext", 0);
-
-  /* pollset->mu already held */
-  if (specific_worker != NULL) {
-    if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
-      GPR_TIMER_BEGIN("pollset_kick_ext.broadcast", 0);
-      GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
-      for (specific_worker = p->root_worker.next;
-           specific_worker != &p->root_worker;
-           specific_worker = specific_worker->next) {
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
-      }
-      p->kicked_without_pollers = 1;
-      GPR_TIMER_END("pollset_kick_ext.broadcast", 0);
-    } else if (gpr_tls_get(&g_current_thread_worker) !=
-               (intptr_t)specific_worker) {
-      GPR_TIMER_MARK("different_thread_worker", 0);
-      if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
-      }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
-    } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
-      GPR_TIMER_MARK("kick_yoself", 0);
-      if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
-      }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
-    }
-  } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
-    GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
-    GPR_TIMER_MARK("kick_anonymous", 0);
-    specific_worker = pop_front_worker(p);
-    if (specific_worker != NULL) {
-      if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
-        GPR_TIMER_MARK("kick_anonymous_not_self", 0);
-        push_back_worker(p, specific_worker);
-        specific_worker = pop_front_worker(p);
-        if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 &&
-            gpr_tls_get(&g_current_thread_worker) ==
-                (intptr_t)specific_worker) {
-          push_back_worker(p, specific_worker);
-          specific_worker = NULL;
-        }
-      }
-      if (specific_worker != NULL) {
-        GPR_TIMER_MARK("finally_kick", 0);
-        push_back_worker(p, specific_worker);
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
-      }
-    } else {
-      GPR_TIMER_MARK("kicked_no_pollers", 0);
-      p->kicked_without_pollers = 1;
-    }
-  }
-
-  GPR_TIMER_END("pollset_kick_ext", 0);
-}
-
-static void pollset_kick(grpc_pollset *p,
-                         grpc_pollset_worker *specific_worker) {
-  pollset_kick_ext(p, specific_worker, 0);
-}
-
-/* global state management */
-
-static void pollset_global_init(void) {
-  gpr_tls_init(&g_current_thread_poller);
-  gpr_tls_init(&g_current_thread_worker);
-  grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
-}
-
-static void pollset_global_shutdown(void) {
-  grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd);
-  gpr_tls_destroy(&g_current_thread_poller);
-  gpr_tls_destroy(&g_current_thread_worker);
-}
-
-static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
-
-/* main interface */
-
-static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null);
-
-static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
-  gpr_mu_init(&pollset->mu);
-  *mu = &pollset->mu;
-  pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker;
-  pollset->in_flight_cbs = 0;
-  pollset->shutting_down = 0;
-  pollset->called_shutdown = 0;
-  pollset->kicked_without_pollers = 0;
-  pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL;
-  pollset->local_wakeup_cache = NULL;
-  pollset->kicked_without_pollers = 0;
-  become_basic_pollset(pollset, NULL);
-}
-
-static void pollset_destroy(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
-  GPR_ASSERT(!pollset_has_workers(pollset));
-  GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
-  pollset->vtable->destroy(pollset);
-  while (pollset->local_wakeup_cache) {
-    grpc_cached_wakeup_fd *next = pollset->local_wakeup_cache->next;
-    grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd);
-    gpr_free(pollset->local_wakeup_cache);
-    pollset->local_wakeup_cache = next;
-  }
-  gpr_mu_destroy(&pollset->mu);
-}
-
-static void pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
-  GPR_ASSERT(!pollset_has_workers(pollset));
-  GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
-  pollset->vtable->destroy(pollset);
-  pollset->shutting_down = 0;
-  pollset->called_shutdown = 0;
-  pollset->kicked_without_pollers = 0;
-  become_basic_pollset(pollset, NULL);
-}
-
-static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           grpc_fd *fd) {
-  gpr_mu_lock(&pollset->mu);
-  pollset->vtable->add_fd(exec_ctx, pollset, fd, 1);
-/* the following (enabled only in debug) will reacquire and then release
-   our lock - meaning that if the unlocking flag passed to add_fd above is
-   not respected, the code will deadlock (in a way that we have a chance of
-   debugging) */
-#ifndef NDEBUG
-  gpr_mu_lock(&pollset->mu);
-  gpr_mu_unlock(&pollset->mu);
-#endif
-}
-
-static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
-  GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs));
-  pollset->vtable->finish_shutdown(pollset);
-  grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
-}
-
-static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         grpc_pollset_worker **worker_hdl, gpr_timespec now,
-                         gpr_timespec deadline) {
-  grpc_pollset_worker worker;
-  *worker_hdl = &worker;
-
-  /* pollset->mu already held */
-  int added_worker = 0;
-  int locked = 1;
-  int queued_work = 0;
-  int keep_polling = 0;
-  GPR_TIMER_BEGIN("pollset_work", 0);
-  /* this must happen before we (potentially) drop pollset->mu */
-  worker.next = worker.prev = NULL;
-  worker.reevaluate_polling_on_wakeup = 0;
-  if (pollset->local_wakeup_cache != NULL) {
-    worker.wakeup_fd = pollset->local_wakeup_cache;
-    pollset->local_wakeup_cache = worker.wakeup_fd->next;
-  } else {
-    worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
-    grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
-  }
-  worker.kicked_specifically = 0;
-  /* If there's work waiting for the pollset to be idle, and the
-     pollset is idle, then do that work */
-  if (!pollset_has_workers(pollset) &&
-      !grpc_closure_list_empty(pollset->idle_jobs)) {
-    GPR_TIMER_MARK("pollset_work.idle_jobs", 0);
-    grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
-    goto done;
-  }
-  /* If we're shutting down then we don't execute any extended work */
-  if (pollset->shutting_down) {
-    GPR_TIMER_MARK("pollset_work.shutting_down", 0);
-    goto done;
-  }
-  /* Give do_promote priority so we don't starve it out */
-  if (pollset->in_flight_cbs) {
-    GPR_TIMER_MARK("pollset_work.in_flight_cbs", 0);
-    gpr_mu_unlock(&pollset->mu);
-    locked = 0;
-    goto done;
-  }
-  /* Start polling, and keep doing so while we're being asked to
-     re-evaluate our pollers (this allows poll() based pollers to
-     ensure they don't miss wakeups) */
-  keep_polling = 1;
-  while (keep_polling) {
-    keep_polling = 0;
-    if (!pollset->kicked_without_pollers) {
-      if (!added_worker) {
-        push_front_worker(pollset, &worker);
-        added_worker = 1;
-        gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
-      }
-      gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset);
-      GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
-      pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker,
-                                             deadline, now);
-      GPR_TIMER_END("maybe_work_and_unlock", 0);
-      locked = 0;
-      gpr_tls_set(&g_current_thread_poller, 0);
-    } else {
-      GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0);
-      pollset->kicked_without_pollers = 0;
-    }
-  /* Finished execution - start cleaning up.
-     Note that we may arrive here from outside the enclosing while() loop.
-     In that case we won't loop though as we haven't added worker to the
-     worker list, which means nobody could ask us to re-evaluate polling). */
-  done:
-    if (!locked) {
-      queued_work |= grpc_exec_ctx_flush(exec_ctx);
-      gpr_mu_lock(&pollset->mu);
-      locked = 1;
-    }
-    /* If we're forced to re-evaluate polling (via pollset_kick with
-       GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force
-       a loop */
-    if (worker.reevaluate_polling_on_wakeup) {
-      worker.reevaluate_polling_on_wakeup = 0;
-      pollset->kicked_without_pollers = 0;
-      if (queued_work || worker.kicked_specifically) {
-        /* If there's queued work on the list, then set the deadline to be
-           immediate so we get back out of the polling loop quickly */
-        deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
-      }
-      keep_polling = 1;
-    }
-  }
-  if (added_worker) {
-    remove_worker(pollset, &worker);
-    gpr_tls_set(&g_current_thread_worker, 0);
-  }
-  /* release wakeup fd to the local pool */
-  worker.wakeup_fd->next = pollset->local_wakeup_cache;
-  pollset->local_wakeup_cache = worker.wakeup_fd;
-  /* check shutdown conditions */
-  if (pollset->shutting_down) {
-    if (pollset_has_workers(pollset)) {
-      pollset_kick(pollset, NULL);
-    } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
-      pollset->called_shutdown = 1;
-      gpr_mu_unlock(&pollset->mu);
-      finish_shutdown(exec_ctx, pollset);
-      grpc_exec_ctx_flush(exec_ctx);
-      /* Continuing to access pollset here is safe -- it is the caller's
-       * responsibility to not destroy when it has outstanding calls to
-       * pollset_work.
-       * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */
-      gpr_mu_lock(&pollset->mu);
-    } else if (!grpc_closure_list_empty(pollset->idle_jobs)) {
-      grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
-      gpr_mu_unlock(&pollset->mu);
-      grpc_exec_ctx_flush(exec_ctx);
-      gpr_mu_lock(&pollset->mu);
-    }
-  }
-  *worker_hdl = NULL;
-  GPR_TIMER_END("pollset_work", 0);
-}
-
-static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                             grpc_closure *closure) {
-  GPR_ASSERT(!pollset->shutting_down);
-  pollset->shutting_down = 1;
-  pollset->shutdown_done = closure;
-  pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
-  if (!pollset_has_workers(pollset)) {
-    grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
-  }
-  if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
-      !pollset_has_workers(pollset)) {
-    pollset->called_shutdown = 1;
-    finish_shutdown(exec_ctx, pollset);
-  }
-}
-
-static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
-                                           gpr_timespec now) {
-  gpr_timespec timeout;
-  static const int64_t max_spin_polling_us = 10;
-  if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
-    return -1;
-  }
-  if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros(
-                                                   max_spin_polling_us,
-                                                   GPR_TIMESPAN))) <= 0) {
-    return 0;
-  }
-  timeout = gpr_time_sub(deadline, now);
-  return gpr_time_to_millis(gpr_time_add(
-      timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
-}
-
-/*
- * basic_pollset - a vtable that provides polling for zero or one file
- *                 descriptor via poll()
- */
-
-typedef struct grpc_unary_promote_args {
-  const grpc_pollset_vtable *original_vtable;
-  grpc_pollset *pollset;
-  grpc_fd *fd;
-  grpc_closure promotion_closure;
-} grpc_unary_promote_args;
-
-static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args,
-                             bool success) {
-  grpc_unary_promote_args *up_args = args;
-  const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
-  grpc_pollset *pollset = up_args->pollset;
-  grpc_fd *fd = up_args->fd;
-
-  /*
-   * This is quite tricky. There are a number of cases to keep in mind here:
-   * 1. fd may have been orphaned
-   * 2. The pollset may no longer be a unary poller (and we can't let case #1
-   * leak to other pollset types!)
-   * 3. pollset's fd (which may have changed) may have been orphaned
-   * 4. The pollset may be shutting down.
-   */
-
-  gpr_mu_lock(&pollset->mu);
-  /* First we need to ensure that nobody is polling concurrently */
-  GPR_ASSERT(!pollset_has_workers(pollset));
-
-  gpr_free(up_args);
-  /* At this point the pollset may no longer be a unary poller. In that case
-   * we should just call the right add function and be done. */
-  /* TODO(klempner): If we're not careful this could cause infinite recursion.
-   * That's not a problem for now because empty_pollset has a trivial poller
-   * and we don't have any mechanism to unbecome multipoller. */
-  pollset->in_flight_cbs--;
-  if (pollset->shutting_down) {
-    /* We don't care about this pollset anymore. */
-    if (pollset->in_flight_cbs == 0 && !pollset->called_shutdown) {
-      pollset->called_shutdown = 1;
-      finish_shutdown(exec_ctx, pollset);
-    }
-  } else if (fd_is_orphaned(fd)) {
-    /* Don't try to add it to anything, we'll drop our ref on it below */
-  } else if (pollset->vtable != original_vtable) {
-    pollset->vtable->add_fd(exec_ctx, pollset, fd, 0);
-  } else if (fd != pollset->data.ptr) {
-    grpc_fd *fds[2];
-    fds[0] = pollset->data.ptr;
-    fds[1] = fd;
-
-    if (fds[0] && !fd_is_orphaned(fds[0])) {
-      platform_become_multipoller(exec_ctx, pollset, fds, GPR_ARRAY_SIZE(fds));
-      GRPC_FD_UNREF(fds[0], "basicpoll");
-    } else {
-      /* old fd is orphaned and we haven't cleaned it up until now, so remain a
-       * unary poller */
-      /* Note that it is possible that fds[1] is also orphaned at this point.
-       * That's okay, we'll correct it at the next add or poll. */
-      if (fds[0]) GRPC_FD_UNREF(fds[0], "basicpoll");
-      pollset->data.ptr = fd;
-      GRPC_FD_REF(fd, "basicpoll");
-    }
-  }
-
-  gpr_mu_unlock(&pollset->mu);
-
-  /* Matching ref in basic_pollset_add_fd */
-  GRPC_FD_UNREF(fd, "basicpoll_add");
-}
-
-static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                                 grpc_fd *fd, int and_unlock_pollset) {
-  grpc_unary_promote_args *up_args;
-  GPR_ASSERT(fd);
-  if (fd == pollset->data.ptr) goto exit;
-
-  if (!pollset_has_workers(pollset)) {
-    /* Fast path -- no in flight cbs */
-    /* TODO(klempner): Comment this out and fix any test failures or establish
-     * they are due to timing issues */
-    grpc_fd *fds[2];
-    fds[0] = pollset->data.ptr;
-    fds[1] = fd;
-
-    if (fds[0] == NULL) {
-      pollset->data.ptr = fd;
-      GRPC_FD_REF(fd, "basicpoll");
-    } else if (!fd_is_orphaned(fds[0])) {
-      platform_become_multipoller(exec_ctx, pollset, fds, GPR_ARRAY_SIZE(fds));
-      GRPC_FD_UNREF(fds[0], "basicpoll");
-    } else {
-      /* old fd is orphaned and we haven't cleaned it up until now, so remain a
-       * unary poller */
-      GRPC_FD_UNREF(fds[0], "basicpoll");
-      pollset->data.ptr = fd;
-      GRPC_FD_REF(fd, "basicpoll");
-    }
-    goto exit;
-  }
-
-  /* Now we need to promote. This needs to happen when we're not polling. Since
-   * this may be called from poll, the wait needs to happen asynchronously. */
-  GRPC_FD_REF(fd, "basicpoll_add");
-  pollset->in_flight_cbs++;
-  up_args = gpr_malloc(sizeof(*up_args));
-  up_args->fd = fd;
-  up_args->original_vtable = pollset->vtable;
-  up_args->pollset = pollset;
-  up_args->promotion_closure.cb = basic_do_promote;
-  up_args->promotion_closure.cb_arg = up_args;
-
-  grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1);
-  pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
-
-exit:
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-  }
-}
-
-static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
-                                                grpc_pollset *pollset,
-                                                grpc_pollset_worker *worker,
-                                                gpr_timespec deadline,
-                                                gpr_timespec now) {
-#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
-#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR)
-
-  struct pollfd pfd[3];
-  grpc_fd *fd;
-  grpc_fd_watcher fd_watcher;
-  int timeout;
-  int r;
-  nfds_t nfds;
-
-  fd = pollset->data.ptr;
-  if (fd && fd_is_orphaned(fd)) {
-    GRPC_FD_UNREF(fd, "basicpoll");
-    fd = pollset->data.ptr = NULL;
-  }
-  timeout = poll_deadline_to_millis_timeout(deadline, now);
-  pfd[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
-  pfd[0].events = POLLIN;
-  pfd[0].revents = 0;
-  pfd[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd);
-  pfd[1].events = POLLIN;
-  pfd[1].revents = 0;
-  nfds = 2;
-  if (fd) {
-    pfd[2].fd = fd->fd;
-    pfd[2].revents = 0;
-    GRPC_FD_REF(fd, "basicpoll_begin");
-    gpr_mu_unlock(&pollset->mu);
-    pfd[2].events =
-        (short)fd_begin_poll(fd, pollset, worker, POLLIN, POLLOUT, &fd_watcher);
-    if (pfd[2].events != 0) {
-      nfds++;
-    }
-  } else {
-    gpr_mu_unlock(&pollset->mu);
-  }
-
-  /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
-     even going into the blocking annotation if possible */
-  /* poll fd count (argument 2) is shortened by one if we have no events
-     to poll on - such that it only includes the kicker */
-  GPR_TIMER_BEGIN("poll", 0);
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  r = grpc_poll_function(pfd, nfds, timeout);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-  GPR_TIMER_END("poll", 0);
-
-  if (r < 0) {
-    if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
-    }
-    if (fd) {
-      fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
-    }
-  } else if (r == 0) {
-    if (fd) {
-      fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
-    }
-  } else {
-    if (pfd[0].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
-    }
-    if (pfd[1].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
-    }
-    if (nfds > 2) {
-      fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK,
-                  pfd[2].revents & POLLOUT_CHECK);
-    } else if (fd) {
-      fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
-    }
-  }
-
-  if (fd) {
-    GRPC_FD_UNREF(fd, "basicpoll_begin");
-  }
-}
-
-static void basic_pollset_destroy(grpc_pollset *pollset) {
-  if (pollset->data.ptr != NULL) {
-    GRPC_FD_UNREF(pollset->data.ptr, "basicpoll");
-    pollset->data.ptr = NULL;
-  }
-}
-
-static const grpc_pollset_vtable basic_pollset = {
-    basic_pollset_add_fd, basic_pollset_maybe_work_and_unlock,
-    basic_pollset_destroy, basic_pollset_destroy};
-
-static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) {
-  pollset->vtable = &basic_pollset;
-  pollset->data.ptr = fd_or_null;
-  if (fd_or_null != NULL) {
-    GRPC_FD_REF(fd_or_null, "basicpoll");
-  }
-}
-
-/*******************************************************************************
- * pollset_multipoller_with_poll_posix.c
- */
-
-#ifndef GPR_LINUX_MULTIPOLL_WITH_EPOLL
-
-typedef struct {
-  /* all polled fds */
-  size_t fd_count;
-  size_t fd_capacity;
-  grpc_fd **fds;
-  /* fds that have been removed from the pollset explicitly */
-  size_t del_count;
-  size_t del_capacity;
-  grpc_fd **dels;
-} poll_hdr;
-
-static void multipoll_with_poll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
-                                               grpc_pollset *pollset,
-                                               grpc_fd *fd,
-                                               int and_unlock_pollset) {
-  size_t i;
-  poll_hdr *h = pollset->data.ptr;
-  /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */
-  for (i = 0; i < h->fd_count; i++) {
-    if (h->fds[i] == fd) goto exit;
-  }
-  if (h->fd_count == h->fd_capacity) {
-    h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2);
-    h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity);
-  }
-  h->fds[h->fd_count++] = fd;
-  GRPC_FD_REF(fd, "multipoller");
-exit:
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-  }
-}
-
-static void multipoll_with_poll_pollset_maybe_work_and_unlock(
-    grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
-    gpr_timespec deadline, gpr_timespec now) {
-#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
-#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR)
-
-  int timeout;
-  int r;
-  size_t i, j, fd_count;
-  nfds_t pfd_count;
-  poll_hdr *h;
-  /* TODO(ctiller): inline some elements to avoid an allocation */
-  grpc_fd_watcher *watchers;
-  struct pollfd *pfds;
-
-  h = pollset->data.ptr;
-  timeout = poll_deadline_to_millis_timeout(deadline, now);
-  /* TODO(ctiller): perform just one malloc here if we exceed the inline case */
-  pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 2));
-  watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 2));
-  fd_count = 0;
-  pfd_count = 2;
-  pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
-  pfds[0].events = POLLIN;
-  pfds[0].revents = 0;
-  pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd);
-  pfds[1].events = POLLIN;
-  pfds[1].revents = 0;
-  for (i = 0; i < h->fd_count; i++) {
-    int remove = fd_is_orphaned(h->fds[i]);
-    for (j = 0; !remove && j < h->del_count; j++) {
-      if (h->fds[i] == h->dels[j]) remove = 1;
-    }
-    if (remove) {
-      GRPC_FD_UNREF(h->fds[i], "multipoller");
-    } else {
-      h->fds[fd_count++] = h->fds[i];
-      watchers[pfd_count].fd = h->fds[i];
-      GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start");
-      pfds[pfd_count].fd = h->fds[i]->fd;
-      pfds[pfd_count].revents = 0;
-      pfd_count++;
-    }
-  }
-  for (j = 0; j < h->del_count; j++) {
-    GRPC_FD_UNREF(h->dels[j], "multipoller_del");
-  }
-  h->del_count = 0;
-  h->fd_count = fd_count;
-  gpr_mu_unlock(&pollset->mu);
-
-  for (i = 2; i < pfd_count; i++) {
-    grpc_fd *fd = watchers[i].fd;
-    pfds[i].events = (short)fd_begin_poll(fd, pollset, worker, POLLIN, POLLOUT,
-                                          &watchers[i]);
-    GRPC_FD_UNREF(fd, "multipoller_start");
-  }
-
-  /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
-     even going into the blocking annotation if possible */
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  r = grpc_poll_function(pfds, pfd_count, timeout);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-
-  if (r < 0) {
-    if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
-    }
-    for (i = 2; i < pfd_count; i++) {
-      fd_end_poll(exec_ctx, &watchers[i], 0, 0);
-    }
-  } else if (r == 0) {
-    for (i = 2; i < pfd_count; i++) {
-      fd_end_poll(exec_ctx, &watchers[i], 0, 0);
-    }
-  } else {
-    if (pfds[0].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
-    }
-    if (pfds[1].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
-    }
-    for (i = 2; i < pfd_count; i++) {
-      if (watchers[i].fd == NULL) {
-        fd_end_poll(exec_ctx, &watchers[i], 0, 0);
-        continue;
-      }
-      fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK,
-                  pfds[i].revents & POLLOUT_CHECK);
-    }
-  }
-
-  gpr_free(pfds);
-  gpr_free(watchers);
-}
-
-static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) {
-  size_t i;
-  poll_hdr *h = pollset->data.ptr;
-  for (i = 0; i < h->fd_count; i++) {
-    GRPC_FD_UNREF(h->fds[i], "multipoller");
-  }
-  for (i = 0; i < h->del_count; i++) {
-    GRPC_FD_UNREF(h->dels[i], "multipoller_del");
-  }
-  h->fd_count = 0;
-  h->del_count = 0;
-}
-
-static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) {
-  poll_hdr *h = pollset->data.ptr;
-  multipoll_with_poll_pollset_finish_shutdown(pollset);
-  gpr_free(h->fds);
-  gpr_free(h->dels);
-  gpr_free(h);
-}
-
-static const grpc_pollset_vtable multipoll_with_poll_pollset = {
-    multipoll_with_poll_pollset_add_fd,
-    multipoll_with_poll_pollset_maybe_work_and_unlock,
-    multipoll_with_poll_pollset_finish_shutdown,
-    multipoll_with_poll_pollset_destroy};
-
-static void poll_become_multipoller(grpc_exec_ctx *exec_ctx,
-                                    grpc_pollset *pollset, grpc_fd **fds,
-                                    size_t nfds) {
-  size_t i;
-  poll_hdr *h = gpr_malloc(sizeof(poll_hdr));
-  pollset->vtable = &multipoll_with_poll_pollset;
-  pollset->data.ptr = h;
-  h->fd_count = nfds;
-  h->fd_capacity = nfds;
-  h->fds = gpr_malloc(nfds * sizeof(grpc_fd *));
-  h->del_count = 0;
-  h->del_capacity = 0;
-  h->dels = NULL;
-  for (i = 0; i < nfds; i++) {
-    h->fds[i] = fds[i];
-    GRPC_FD_REF(fds[i], "multipoller");
-  }
-}
-
-#endif /* !GPR_LINUX_MULTIPOLL_WITH_EPOLL */
-
-/*******************************************************************************
- * pollset_multipoller_with_epoll_posix.c
- */
-
-#ifdef GPR_LINUX_MULTIPOLL_WITH_EPOLL
-
-#include <errno.h>
-#include <poll.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/profiling/timers.h"
-#include "src/core/lib/support/block_annotate.h"
-
-static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure **st) {
-  /* only one set_ready can be active at once (but there may be a racing
-     notify_on) */
-  gpr_mu_lock(&fd->mu);
-  set_ready_locked(exec_ctx, fd, st);
-  gpr_mu_unlock(&fd->mu);
-}
-
-static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  set_ready(exec_ctx, fd, &fd->read_closure);
-}
-
-static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  set_ready(exec_ctx, fd, &fd->write_closure);
-}
-
-struct epoll_fd_list {
-  int *epoll_fds;
-  size_t count;
-  size_t capacity;
-};
-
-static struct epoll_fd_list epoll_fd_global_list;
-static gpr_once init_epoll_fd_list_mu = GPR_ONCE_INIT;
-static gpr_mu epoll_fd_list_mu;
-
-static void init_mu(void) { gpr_mu_init(&epoll_fd_list_mu); }
-
-static void add_epoll_fd_to_global_list(int epoll_fd) {
-  gpr_once_init(&init_epoll_fd_list_mu, init_mu);
-
-  gpr_mu_lock(&epoll_fd_list_mu);
-  if (epoll_fd_global_list.count == epoll_fd_global_list.capacity) {
-    epoll_fd_global_list.capacity =
-        GPR_MAX((size_t)8, epoll_fd_global_list.capacity * 2);
-    epoll_fd_global_list.epoll_fds =
-        gpr_realloc(epoll_fd_global_list.epoll_fds,
-                    epoll_fd_global_list.capacity * sizeof(int));
-  }
-  epoll_fd_global_list.epoll_fds[epoll_fd_global_list.count++] = epoll_fd;
-  gpr_mu_unlock(&epoll_fd_list_mu);
-}
-
-static void remove_epoll_fd_from_global_list(int epoll_fd) {
-  gpr_mu_lock(&epoll_fd_list_mu);
-  GPR_ASSERT(epoll_fd_global_list.count > 0);
-  for (size_t i = 0; i < epoll_fd_global_list.count; i++) {
-    if (epoll_fd == epoll_fd_global_list.epoll_fds[i]) {
-      epoll_fd_global_list.epoll_fds[i] =
-          epoll_fd_global_list.epoll_fds[--(epoll_fd_global_list.count)];
-      break;
-    }
-  }
-  gpr_mu_unlock(&epoll_fd_list_mu);
-}
-
-static void remove_fd_from_all_epoll_sets(int fd) {
-  int err;
-  gpr_once_init(&init_epoll_fd_list_mu, init_mu);
-  gpr_mu_lock(&epoll_fd_list_mu);
-  if (epoll_fd_global_list.count == 0) {
-    gpr_mu_unlock(&epoll_fd_list_mu);
-    return;
-  }
-  for (size_t i = 0; i < epoll_fd_global_list.count; i++) {
-    err = epoll_ctl(epoll_fd_global_list.epoll_fds[i], EPOLL_CTL_DEL, fd, NULL);
-    if (err < 0 && errno != ENOENT) {
-      gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd,
-              strerror(errno));
-    }
-  }
-  gpr_mu_unlock(&epoll_fd_list_mu);
-}
-
-typedef struct {
-  grpc_pollset *pollset;
-  grpc_fd *fd;
-  grpc_closure closure;
-} delayed_add;
-
-typedef struct { int epoll_fd; } epoll_hdr;
-
-static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                           grpc_fd *fd) {
-  epoll_hdr *h = pollset->data.ptr;
-  struct epoll_event ev;
-  int err;
-  grpc_fd_watcher watcher;
-
-  /* We pretend to be polling whilst adding an fd to keep the fd from being
-     closed during the add. This may result in a spurious wakeup being assigned
-     to this pollset whilst adding, but that should be benign. */
-  GPR_ASSERT(fd_begin_poll(fd, pollset, NULL, 0, 0, &watcher) == 0);
-  if (watcher.fd != NULL) {
-    ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET);
-    ev.data.ptr = fd;
-    err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, fd->fd, &ev);
-    if (err < 0) {
-      /* FDs may be added to a pollset multiple times, so EEXIST is normal. */
-      if (errno != EEXIST) {
-        gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", fd->fd,
-                strerror(errno));
-      }
-    }
-  }
-  fd_end_poll(exec_ctx, &watcher, 0, 0);
-}
-
-static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg,
-                                bool iomgr_status) {
-  delayed_add *da = arg;
-
-  if (!fd_is_orphaned(da->fd)) {
-    finally_add_fd(exec_ctx, da->pollset, da->fd);
-  }
-
-  gpr_mu_lock(&da->pollset->mu);
-  da->pollset->in_flight_cbs--;
-  if (da->pollset->shutting_down) {
-    /* We don't care about this pollset anymore. */
-    if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) {
-      da->pollset->called_shutdown = 1;
-      grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, true, NULL);
-    }
-  }
-  gpr_mu_unlock(&da->pollset->mu);
-
-  GRPC_FD_UNREF(da->fd, "delayed_add");
-
-  gpr_free(da);
-}
-
-static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
-                                                grpc_pollset *pollset,
-                                                grpc_fd *fd,
-                                                int and_unlock_pollset) {
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-    finally_add_fd(exec_ctx, pollset, fd);
-  } else {
-    delayed_add *da = gpr_malloc(sizeof(*da));
-    da->pollset = pollset;
-    da->fd = fd;
-    GRPC_FD_REF(fd, "delayed_add");
-    grpc_closure_init(&da->closure, perform_delayed_add, da);
-    pollset->in_flight_cbs++;
-    grpc_exec_ctx_enqueue(exec_ctx, &da->closure, true, NULL);
-  }
-}
-
-/* TODO(klempner): We probably want to turn this down a bit */
-#define GRPC_EPOLL_MAX_EVENTS 1000
-
-static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
-    grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
-    gpr_timespec deadline, gpr_timespec now) {
-  struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS];
-  int ep_rv;
-  int poll_rv;
-  epoll_hdr *h = pollset->data.ptr;
-  int timeout_ms;
-  struct pollfd pfds[2];
-
-  /* If you want to ignore epoll's ability to sanely handle parallel pollers,
-   * for a more apples-to-apples performance comparison with poll, add a
-   * if (pollset->counter != 0) { return 0; }
-   * here.
-   */
-
-  gpr_mu_unlock(&pollset->mu);
-
-  timeout_ms = poll_deadline_to_millis_timeout(deadline, now);
-
-  pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd);
-  pfds[0].events = POLLIN;
-  pfds[0].revents = 0;
-  pfds[1].fd = h->epoll_fd;
-  pfds[1].events = POLLIN;
-  pfds[1].revents = 0;
-
-  /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
-     even going into the blocking annotation if possible */
-  GPR_TIMER_BEGIN("poll", 0);
-  GRPC_SCHEDULING_START_BLOCKING_REGION;
-  poll_rv = grpc_poll_function(pfds, 2, timeout_ms);
-  GRPC_SCHEDULING_END_BLOCKING_REGION;
-  GPR_TIMER_END("poll", 0);
-
-  if (poll_rv < 0) {
-    if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
-    }
-  } else if (poll_rv == 0) {
-    /* do nothing */
-  } else {
-    if (pfds[0].revents) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
-    }
-    if (pfds[1].revents) {
-      do {
-        /* The following epoll_wait never blocks; it has a timeout of 0 */
-        ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0);
-        if (ep_rv < 0) {
-          if (errno != EINTR) {
-            gpr_log(GPR_ERROR, "epoll_wait() failed: %s", strerror(errno));
-          }
-        } else {
-          int i;
-          for (i = 0; i < ep_rv; ++i) {
-            grpc_fd *fd = ep_ev[i].data.ptr;
-            /* TODO(klempner): We might want to consider making err and pri
-             * separate events */
-            int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP);
-            int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI);
-            int write_ev = ep_ev[i].events & EPOLLOUT;
-            if (fd == NULL) {
-              grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
-            } else {
-              if (read_ev || cancel) {
-                fd_become_readable(exec_ctx, fd);
-              }
-              if (write_ev || cancel) {
-                fd_become_writable(exec_ctx, fd);
-              }
-            }
-          }
-        }
-      } while (ep_rv == GRPC_EPOLL_MAX_EVENTS);
-    }
-  }
-}
-
-static void multipoll_with_epoll_pollset_finish_shutdown(
-    grpc_pollset *pollset) {}
-
-static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) {
-  epoll_hdr *h = pollset->data.ptr;
-  close(h->epoll_fd);
-  remove_epoll_fd_from_global_list(h->epoll_fd);
-  gpr_free(h);
-}
-
-static const grpc_pollset_vtable multipoll_with_epoll_pollset = {
-    multipoll_with_epoll_pollset_add_fd,
-    multipoll_with_epoll_pollset_maybe_work_and_unlock,
-    multipoll_with_epoll_pollset_finish_shutdown,
-    multipoll_with_epoll_pollset_destroy};
-
-static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
-                                     grpc_pollset *pollset, grpc_fd **fds,
-                                     size_t nfds) {
-  size_t i;
-  epoll_hdr *h = gpr_malloc(sizeof(epoll_hdr));
-  struct epoll_event ev;
-  int err;
-
-  pollset->vtable = &multipoll_with_epoll_pollset;
-  pollset->data.ptr = h;
-  h->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-  if (h->epoll_fd < 0) {
-    /* TODO(klempner): Fall back to poll here, especially on ENOSYS */
-    gpr_log(GPR_ERROR, "epoll_create1 failed: %s", strerror(errno));
-    abort();
-  }
-  add_epoll_fd_to_global_list(h->epoll_fd);
-
-  ev.events = (uint32_t)(EPOLLIN | EPOLLET);
-  ev.data.ptr = NULL;
-  err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD,
-                  GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), &ev);
-  if (err < 0) {
-    gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s",
-            GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd),
-            strerror(errno));
-  }
-
-  for (i = 0; i < nfds; i++) {
-    multipoll_with_epoll_pollset_add_fd(exec_ctx, pollset, fds[i], 0);
-  }
-}
-
-#else /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
-
-static void remove_fd_from_all_epoll_sets(int fd) {}
-
-#endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
-
-/*******************************************************************************
- * pollset_set_posix.c
- */
-
-static grpc_pollset_set *pollset_set_create(void) {
-  grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set));
-  memset(pollset_set, 0, sizeof(*pollset_set));
-  gpr_mu_init(&pollset_set->mu);
-  return pollset_set;
-}
-
-static void pollset_set_destroy(grpc_pollset_set *pollset_set) {
-  size_t i;
-  gpr_mu_destroy(&pollset_set->mu);
-  for (i = 0; i < pollset_set->fd_count; i++) {
-    GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
-  }
-  gpr_free(pollset_set->pollsets);
-  gpr_free(pollset_set->pollset_sets);
-  gpr_free(pollset_set->fds);
-  gpr_free(pollset_set);
-}
-
-static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
-                                    grpc_pollset_set *pollset_set,
-                                    grpc_pollset *pollset) {
-  size_t i, j;
-  gpr_mu_lock(&pollset_set->mu);
-  if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
-    pollset_set->pollset_capacity =
-        GPR_MAX(8, 2 * pollset_set->pollset_capacity);
-    pollset_set->pollsets =
-        gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity *
-                                               sizeof(*pollset_set->pollsets));
-  }
-  pollset_set->pollsets[pollset_set->pollset_count++] = pollset;
-  for (i = 0, j = 0; i < pollset_set->fd_count; i++) {
-    if (fd_is_orphaned(pollset_set->fds[i])) {
-      GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
-    } else {
-      pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]);
-      pollset_set->fds[j++] = pollset_set->fds[i];
-    }
-  }
-  pollset_set->fd_count = j;
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
-                                    grpc_pollset_set *pollset_set,
-                                    grpc_pollset *pollset) {
-  size_t i;
-  gpr_mu_lock(&pollset_set->mu);
-  for (i = 0; i < pollset_set->pollset_count; i++) {
-    if (pollset_set->pollsets[i] == pollset) {
-      pollset_set->pollset_count--;
-      GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i],
-               pollset_set->pollsets[pollset_set->pollset_count]);
-      break;
-    }
-  }
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
-                                        grpc_pollset_set *bag,
-                                        grpc_pollset_set *item) {
-  size_t i, j;
-  gpr_mu_lock(&bag->mu);
-  if (bag->pollset_set_count == bag->pollset_set_capacity) {
-    bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity);
-    bag->pollset_sets =
-        gpr_realloc(bag->pollset_sets,
-                    bag->pollset_set_capacity * sizeof(*bag->pollset_sets));
-  }
-  bag->pollset_sets[bag->pollset_set_count++] = item;
-  for (i = 0, j = 0; i < bag->fd_count; i++) {
-    if (fd_is_orphaned(bag->fds[i])) {
-      GRPC_FD_UNREF(bag->fds[i], "pollset_set");
-    } else {
-      pollset_set_add_fd(exec_ctx, item, bag->fds[i]);
-      bag->fds[j++] = bag->fds[i];
-    }
-  }
-  bag->fd_count = j;
-  gpr_mu_unlock(&bag->mu);
-}
-
-static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
-                                        grpc_pollset_set *bag,
-                                        grpc_pollset_set *item) {
-  size_t i;
-  gpr_mu_lock(&bag->mu);
-  for (i = 0; i < bag->pollset_set_count; i++) {
-    if (bag->pollset_sets[i] == item) {
-      bag->pollset_set_count--;
-      GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i],
-               bag->pollset_sets[bag->pollset_set_count]);
-      break;
-    }
-  }
-  gpr_mu_unlock(&bag->mu);
-}
-
-static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
-                               grpc_pollset_set *pollset_set, grpc_fd *fd) {
-  size_t i;
-  gpr_mu_lock(&pollset_set->mu);
-  if (pollset_set->fd_count == pollset_set->fd_capacity) {
-    pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity);
-    pollset_set->fds = gpr_realloc(
-        pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds));
-  }
-  GRPC_FD_REF(fd, "pollset_set");
-  pollset_set->fds[pollset_set->fd_count++] = fd;
-  for (i = 0; i < pollset_set->pollset_count; i++) {
-    pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd);
-  }
-  for (i = 0; i < pollset_set->pollset_set_count; i++) {
-    pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
-  }
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
-                               grpc_pollset_set *pollset_set, grpc_fd *fd) {
-  size_t i;
-  gpr_mu_lock(&pollset_set->mu);
-  for (i = 0; i < pollset_set->fd_count; i++) {
-    if (pollset_set->fds[i] == fd) {
-      pollset_set->fd_count--;
-      GPR_SWAP(grpc_fd *, pollset_set->fds[i],
-               pollset_set->fds[pollset_set->fd_count]);
-      GRPC_FD_UNREF(fd, "pollset_set");
-      break;
-    }
-  }
-  for (i = 0; i < pollset_set->pollset_set_count; i++) {
-    pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
-  }
-  gpr_mu_unlock(&pollset_set->mu);
-}
-
-/*******************************************************************************
- * event engine binding
- */
-
-static void shutdown_engine(void) {
-  fd_global_shutdown();
-  pollset_global_shutdown();
-}
-
-static const grpc_event_engine_vtable vtable = {
-    .pollset_size = sizeof(grpc_pollset),
-
-    .fd_create = fd_create,
-    .fd_wrapped_fd = fd_wrapped_fd,
-    .fd_orphan = fd_orphan,
-    .fd_shutdown = fd_shutdown,
-    .fd_notify_on_read = fd_notify_on_read,
-    .fd_notify_on_write = fd_notify_on_write,
-
-    .pollset_init = pollset_init,
-    .pollset_shutdown = pollset_shutdown,
-    .pollset_reset = pollset_reset,
-    .pollset_destroy = pollset_destroy,
-    .pollset_work = pollset_work,
-    .pollset_kick = pollset_kick,
-    .pollset_add_fd = pollset_add_fd,
-
-    .pollset_set_create = pollset_set_create,
-    .pollset_set_destroy = pollset_set_destroy,
-    .pollset_set_add_pollset = pollset_set_add_pollset,
-    .pollset_set_del_pollset = pollset_set_del_pollset,
-    .pollset_set_add_pollset_set = pollset_set_add_pollset_set,
-    .pollset_set_del_pollset_set = pollset_set_del_pollset_set,
-    .pollset_set_add_fd = pollset_set_add_fd,
-    .pollset_set_del_fd = pollset_set_del_fd,
-
-    .kick_poller = kick_poller,
-
-    .shutdown_engine = shutdown_engine,
-};
-
-const grpc_event_engine_vtable *grpc_init_poll_and_epoll_posix(void) {
-#ifdef GPR_LINUX_MULTIPOLL_WITH_EPOLL
-  platform_become_multipoller = epoll_become_multipoller;
-#else
-  platform_become_multipoller = poll_become_multipoller;
-#endif
-  fd_global_init();
-  pollset_global_init();
-  return &vtable;
-}
-
-#endif
diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.h b/src/core/lib/iomgr/ev_poll_and_epoll_posix.h
deleted file mode 100644
index 06d6dbf..0000000
--- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Copyright 2015, 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_IOMGR_EV_POLL_AND_EPOLL_POSIX_H
-#define GRPC_CORE_LIB_IOMGR_EV_POLL_AND_EPOLL_POSIX_H
-
-#include "src/core/lib/iomgr/ev_posix.h"
-
-const grpc_event_engine_vtable *grpc_init_poll_and_epoll_posix(void);
-
-#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_AND_EPOLL_POSIX_H */
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index e91ae40..e2a2123 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -59,6 +59,8 @@
  * FD declarations
  */
 
+grpc_wakeup_fd grpc_global_wakeup_fd;
+
 typedef struct grpc_fd_watcher {
   struct grpc_fd_watcher *next;
   struct grpc_fd_watcher *prev;
@@ -113,6 +115,9 @@
   grpc_closure *on_done_closure;
 
   grpc_iomgr_object iomgr_object;
+
+  /* The pollset that last noticed and notified that the fd is readable */
+  grpc_pollset *read_notifier_pollset;
 };
 
 /* Begin polling on an fd.
@@ -134,7 +139,8 @@
    if got_read or got_write are 1, also does the become_{readable,writable} as
    appropriate. */
 static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
-                        int got_read, int got_write);
+                        int got_read, int got_write,
+                        grpc_pollset *read_notifier_pollset);
 
 /* Return 1 if this fd is orphaned, 0 otherwise */
 static bool fd_is_orphaned(grpc_fd *fd);
@@ -177,7 +183,6 @@
 struct grpc_pollset {
   gpr_mu mu;
   grpc_pollset_worker root_worker;
-  int in_flight_cbs;
   int shutting_down;
   int called_shutdown;
   int kicked_without_pollers;
@@ -187,10 +192,6 @@
   size_t fd_count;
   size_t fd_capacity;
   grpc_fd **fds;
-  /* fds that have been removed from the pollset explicitly */
-  size_t del_count;
-  size_t del_capacity;
-  grpc_fd **dels;
   /* Local cache of eventfds for workers */
   grpc_cached_wakeup_fd *local_wakeup_cache;
 };
@@ -301,6 +302,7 @@
   r->on_done_closure = NULL;
   r->closed = 0;
   r->released = 0;
+  r->read_notifier_pollset = NULL;
 
   char *name2;
   gpr_asprintf(&name2, "%s fd=%d", name, fd);
@@ -316,6 +318,18 @@
   return (gpr_atm_acq_load(&fd->refst) & 1) == 0;
 }
 
+/* Return the read-notifier pollset */
+static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
+                                                  grpc_fd *fd) {
+  grpc_pollset *notifier = NULL;
+
+  gpr_mu_lock(&fd->mu);
+  notifier = fd->read_notifier_pollset;
+  gpr_mu_unlock(&fd->mu);
+
+  return notifier;
+}
+
 static void pollset_kick_locked(grpc_fd_watcher *watcher) {
   gpr_mu_lock(&watcher->pollset->mu);
   GPR_ASSERT(watcher->worker);
@@ -444,6 +458,11 @@
   }
 }
 
+static void set_read_notifier_pollset_locked(
+    grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *read_notifier_pollset) {
+  fd->read_notifier_pollset = read_notifier_pollset;
+}
+
 static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
   gpr_mu_lock(&fd->mu);
   GPR_ASSERT(!fd->shutdown);
@@ -519,7 +538,8 @@
 }
 
 static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher,
-                        int got_read, int got_write) {
+                        int got_read, int got_write,
+                        grpc_pollset *read_notifier_pollset) {
   int was_polling = 0;
   int kick = 0;
   grpc_fd *fd = watcher->fd;
@@ -555,6 +575,9 @@
     if (set_ready_locked(exec_ctx, fd, &fd->read_closure)) {
       kick = 1;
     }
+    if (read_notifier_pollset != NULL) {
+      set_read_notifier_pollset_locked(exec_ctx, fd, read_notifier_pollset);
+    }
   }
   if (got_write) {
     if (set_ready_locked(exec_ctx, fd, &fd->write_closure)) {
@@ -700,7 +723,6 @@
   gpr_mu_init(&pollset->mu);
   *mu = &pollset->mu;
   pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker;
-  pollset->in_flight_cbs = 0;
   pollset->shutting_down = 0;
   pollset->called_shutdown = 0;
   pollset->kicked_without_pollers = 0;
@@ -709,14 +731,10 @@
   pollset->kicked_without_pollers = 0;
   pollset->fd_count = 0;
   pollset->fd_capacity = 0;
-  pollset->del_count = 0;
-  pollset->del_capacity = 0;
   pollset->fds = NULL;
-  pollset->dels = NULL;
 }
 
 static void pollset_destroy(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
   GPR_ASSERT(!pollset_has_workers(pollset));
   GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
   while (pollset->local_wakeup_cache) {
@@ -726,17 +744,14 @@
     pollset->local_wakeup_cache = next;
   }
   gpr_free(pollset->fds);
-  gpr_free(pollset->dels);
   gpr_mu_destroy(&pollset->mu);
 }
 
 static void pollset_reset(grpc_pollset *pollset) {
   GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(pollset->in_flight_cbs == 0);
   GPR_ASSERT(!pollset_has_workers(pollset));
   GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
   GPR_ASSERT(pollset->fd_count == 0);
-  GPR_ASSERT(pollset->del_count == 0);
   pollset->shutting_down = 0;
   pollset->called_shutdown = 0;
   pollset->kicked_without_pollers = 0;
@@ -769,11 +784,7 @@
   for (i = 0; i < pollset->fd_count; i++) {
     GRPC_FD_UNREF(pollset->fds[i], "multipoller");
   }
-  for (i = 0; i < pollset->del_count; i++) {
-    GRPC_FD_UNREF(pollset->dels[i], "multipoller_del");
-  }
   pollset->fd_count = 0;
-  pollset->del_count = 0;
   grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
 }
 
@@ -813,13 +824,6 @@
     GPR_TIMER_MARK("pollset_work.shutting_down", 0);
     goto done;
   }
-  /* Give do_promote priority so we don't starve it out */
-  if (pollset->in_flight_cbs) {
-    GPR_TIMER_MARK("pollset_work.in_flight_cbs", 0);
-    gpr_mu_unlock(&pollset->mu);
-    locked = 0;
-    goto done;
-  }
   /* Start polling, and keep doing so while we're being asked to
      re-evaluate our pollers (this allows poll() based pollers to
      ensure they don't miss wakeups) */
@@ -839,7 +843,7 @@
 
       int timeout;
       int r;
-      size_t i, j, fd_count;
+      size_t i, fd_count;
       nfds_t pfd_count;
       /* TODO(ctiller): inline some elements to avoid an allocation */
       grpc_fd_watcher *watchers;
@@ -859,11 +863,7 @@
       pfds[1].events = POLLIN;
       pfds[1].revents = 0;
       for (i = 0; i < pollset->fd_count; i++) {
-        int remove = fd_is_orphaned(pollset->fds[i]);
-        for (j = 0; !remove && j < pollset->del_count; j++) {
-          if (pollset->fds[i] == pollset->dels[j]) remove = 1;
-        }
-        if (remove) {
+        if (fd_is_orphaned(pollset->fds[i])) {
           GRPC_FD_UNREF(pollset->fds[i], "multipoller");
         } else {
           pollset->fds[fd_count++] = pollset->fds[i];
@@ -874,10 +874,6 @@
           pfd_count++;
         }
       }
-      for (j = 0; j < pollset->del_count; j++) {
-        GRPC_FD_UNREF(pollset->dels[j], "multipoller_del");
-      }
-      pollset->del_count = 0;
       pollset->fd_count = fd_count;
       gpr_mu_unlock(&pollset->mu);
 
@@ -899,11 +895,11 @@
           gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
         }
         for (i = 2; i < pfd_count; i++) {
-          fd_end_poll(exec_ctx, &watchers[i], 0, 0);
+          fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
         }
       } else if (r == 0) {
         for (i = 2; i < pfd_count; i++) {
-          fd_end_poll(exec_ctx, &watchers[i], 0, 0);
+          fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
         }
       } else {
         if (pfds[0].revents & POLLIN_CHECK) {
@@ -914,10 +910,10 @@
         }
         for (i = 2; i < pfd_count; i++) {
           if (watchers[i].fd == NULL) {
-            fd_end_poll(exec_ctx, &watchers[i], 0, 0);
+            fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
           } else {
             fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK,
-                        pfds[i].revents & POLLOUT_CHECK);
+                        pfds[i].revents & POLLOUT_CHECK, pollset);
           }
         }
       }
@@ -969,7 +965,7 @@
   if (pollset->shutting_down) {
     if (pollset_has_workers(pollset)) {
       pollset_kick(pollset, NULL);
-    } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
+    } else if (!pollset->called_shutdown) {
       pollset->called_shutdown = 1;
       gpr_mu_unlock(&pollset->mu);
       finish_shutdown(exec_ctx, pollset);
@@ -999,8 +995,7 @@
   if (!pollset_has_workers(pollset)) {
     grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
   }
-  if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 &&
-      !pollset_has_workers(pollset)) {
+  if (!pollset->called_shutdown && !pollset_has_workers(pollset)) {
     pollset->called_shutdown = 1;
     finish_shutdown(exec_ctx, pollset);
   }
@@ -1181,6 +1176,7 @@
     .fd_shutdown = fd_shutdown,
     .fd_notify_on_read = fd_notify_on_read,
     .fd_notify_on_write = fd_notify_on_write,
+    .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
 
     .pollset_init = pollset_init,
     .pollset_shutdown = pollset_shutdown,
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index a7dfc95..95520b0 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -44,7 +44,6 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h"
 #include "src/core/lib/iomgr/ev_poll_posix.h"
 #include "src/core/lib/support/env.h"
 
@@ -62,7 +61,7 @@
 } event_engine_factory;
 
 static const event_engine_factory g_factories[] = {
-    {"poll", grpc_init_poll_posix}, {"legacy", grpc_init_poll_and_epoll_posix},
+    {"poll", grpc_init_poll_posix},
 };
 
 static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
@@ -163,6 +162,11 @@
   g_event_engine->fd_notify_on_write(exec_ctx, fd, closure);
 }
 
+grpc_pollset *grpc_fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
+                                                grpc_fd *fd) {
+  return g_event_engine->fd_get_read_notifier_pollset(exec_ctx, fd);
+}
+
 size_t grpc_pollset_size(void) { return g_event_engine->pollset_size; }
 
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 1fa9f5e..344bf63 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -55,6 +55,8 @@
                             grpc_closure *closure);
   void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                              grpc_closure *closure);
+  grpc_pollset *(*fd_get_read_notifier_pollset)(grpc_exec_ctx *exec_ctx,
+                                                grpc_fd *fd);
 
   void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu);
   void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -137,6 +139,10 @@
 void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                              grpc_closure *closure);
 
+/* Return the read notifier pollset from the fd */
+grpc_pollset *grpc_fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
+                                                grpc_fd *fd);
+
 /* pollset_posix functions */
 
 /* Add an fd to a pollset */
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
index 99b9f29..fee14ae 100644
--- a/src/core/lib/iomgr/tcp_server.h
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -52,6 +52,7 @@
 /* Called for newly connected TCP connections. */
 typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
                                    grpc_endpoint *ep,
+                                   grpc_pollset *accepting_pollset,
                                    grpc_tcp_server_acceptor *acceptor);
 
 /* Create a server, initially not bound to any ports. The caller owns one ref.
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index aaeb384..909e34a 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -128,6 +128,9 @@
   grpc_pollset **pollsets;
   /* number of pollsets in the pollsets array */
   size_t pollset_count;
+
+  /* next pollset to assign a channel to */
+  size_t next_pollset_to_assign;
 };
 
 grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
@@ -145,6 +148,7 @@
   s->head = NULL;
   s->tail = NULL;
   s->nports = 0;
+  s->next_pollset_to_assign = 0;
   return s;
 }
 
@@ -310,13 +314,17 @@
   grpc_tcp_listener *sp = arg;
   grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
                                        sp->fd_index};
+  grpc_pollset *read_notifier_pollset = NULL;
   grpc_fd *fdobj;
-  size_t i;
 
   if (!success) {
     goto error;
   }
 
+  read_notifier_pollset =
+      sp->server->pollsets[(sp->server->next_pollset_to_assign++) %
+                           sp->server->pollset_count];
+
   /* loop until accept4 returns EAGAIN, and then re-arm notification */
   for (;;) {
     struct sockaddr_storage addr;
@@ -349,16 +357,18 @@
     }
 
     fdobj = grpc_fd_create(fd, name);
-    /* TODO(ctiller): revise this when we have server-side sharding
-       of channels -- we certainly should not be automatically adding every
-       incoming channel to every pollset owned by the server */
-    for (i = 0; i < sp->server->pollset_count; i++) {
-      grpc_pollset_add_fd(exec_ctx, sp->server->pollsets[i], fdobj);
+
+    if (read_notifier_pollset == NULL) {
+      gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd");
+      goto error;
     }
+
+    grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
+
     sp->server->on_accept_cb(
         exec_ctx, sp->server->on_accept_cb_arg,
         grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str),
-        &acceptor);
+        read_notifier_pollset, &acceptor);
 
     gpr_free(name);
     gpr_free(addr_str);
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 125f521..e15f8b0 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -379,9 +379,10 @@
 
   /* The only time we should call our callback, is where we successfully
      managed to accept a connection, and created an endpoint. */
-  if (ep)
-    sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep,
+  if (ep) {
+    sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, NULL,
                              &acceptor);
+  }
   /* As we were notified from the IOCP of one and exactly one accept,
      the former socked we created has now either been destroy or assigned
      to the new connection. We need to create a new one for the next
diff --git a/src/core/lib/security/auth_filters.h b/src/core/lib/security/auth_filters.h
deleted file mode 100644
index 7fb56c3..0000000
--- a/src/core/lib/security/auth_filters.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_AUTH_FILTERS_H
-#define GRPC_CORE_LIB_SECURITY_AUTH_FILTERS_H
-
-#include "src/core/lib/channel/channel_stack.h"
-
-extern const grpc_channel_filter grpc_client_auth_filter;
-extern const grpc_channel_filter grpc_server_auth_filter;
-
-#endif /* GRPC_CORE_LIB_SECURITY_AUTH_FILTERS_H */
diff --git a/src/core/lib/security/b64.c b/src/core/lib/security/b64.c
deleted file mode 100644
index 87f0e05..0000000
--- a/src/core/lib/security/b64.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/b64.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-
-/* --- Constants. --- */
-
-static const int8_t base64_bytes[] = {
-    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-    -1,   -1,   -1,   -1,   -1,   -1,   -1,   0x3E, -1,   -1,   -1,   0x3F,
-    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1,   -1,
-    -1,   0x7F, -1,   -1,   -1,   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
-    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1,   -1,   -1,   -1,   -1,
-    -1,   0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
-    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
-    0x31, 0x32, 0x33, -1,   -1,   -1,   -1,   -1};
-
-static const char base64_url_unsafe_chars[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char base64_url_safe_chars[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-
-#define GRPC_BASE64_PAD_CHAR '='
-#define GRPC_BASE64_PAD_BYTE 0x7F
-#define GRPC_BASE64_MULTILINE_LINE_LEN 76
-#define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4)
-
-/* --- base64 functions. --- */
-
-char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
-                         int multiline) {
-  const unsigned char *data = vdata;
-  const char *base64_chars =
-      url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
-  size_t result_projected_size =
-      4 * ((data_size + 3) / 3) +
-      2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS))
-                     : 0) +
-      1;
-  char *result = gpr_malloc(result_projected_size);
-  char *current = result;
-  size_t num_blocks = 0;
-  size_t i = 0;
-
-  /* Encode each block. */
-  while (data_size >= 3) {
-    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
-    *current++ =
-        base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
-    *current++ =
-        base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)];
-    *current++ = base64_chars[data[i + 2] & 0x3F];
-
-    data_size -= 3;
-    i += 3;
-    if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) {
-      *current++ = '\r';
-      *current++ = '\n';
-      num_blocks = 0;
-    }
-  }
-
-  /* Take care of the tail. */
-  if (data_size == 2) {
-    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
-    *current++ =
-        base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
-    *current++ = base64_chars[(data[i + 1] & 0x0F) << 2];
-    *current++ = GRPC_BASE64_PAD_CHAR;
-  } else if (data_size == 1) {
-    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
-    *current++ = base64_chars[(data[i] & 0x03) << 4];
-    *current++ = GRPC_BASE64_PAD_CHAR;
-    *current++ = GRPC_BASE64_PAD_CHAR;
-  }
-
-  GPR_ASSERT(current >= result);
-  GPR_ASSERT((uintptr_t)(current - result) < result_projected_size);
-  result[current - result] = '\0';
-  return result;
-}
-
-gpr_slice grpc_base64_decode(const char *b64, int url_safe) {
-  return grpc_base64_decode_with_len(b64, strlen(b64), url_safe);
-}
-
-static void decode_one_char(const unsigned char *codes, unsigned char *result,
-                            size_t *result_offset) {
-  uint32_t packed = ((uint32_t)codes[0] << 2) | ((uint32_t)codes[1] >> 4);
-  result[(*result_offset)++] = (unsigned char)packed;
-}
-
-static void decode_two_chars(const unsigned char *codes, unsigned char *result,
-                             size_t *result_offset) {
-  uint32_t packed = ((uint32_t)codes[0] << 10) | ((uint32_t)codes[1] << 4) |
-                    ((uint32_t)codes[2] >> 2);
-  result[(*result_offset)++] = (unsigned char)(packed >> 8);
-  result[(*result_offset)++] = (unsigned char)(packed);
-}
-
-static int decode_group(const unsigned char *codes, size_t num_codes,
-                        unsigned char *result, size_t *result_offset) {
-  GPR_ASSERT(num_codes <= 4);
-
-  /* Short end groups that may not have padding. */
-  if (num_codes == 1) {
-    gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes.");
-    return 0;
-  }
-  if (num_codes == 2) {
-    decode_one_char(codes, result, result_offset);
-    return 1;
-  }
-  if (num_codes == 3) {
-    decode_two_chars(codes, result, result_offset);
-    return 1;
-  }
-
-  /* Regular 4 byte groups with padding or not. */
-  GPR_ASSERT(num_codes == 4);
-  if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) {
-    gpr_log(GPR_ERROR, "Invalid padding detected.");
-    return 0;
-  }
-  if (codes[2] == GRPC_BASE64_PAD_BYTE) {
-    if (codes[3] == GRPC_BASE64_PAD_BYTE) {
-      decode_one_char(codes, result, result_offset);
-    } else {
-      gpr_log(GPR_ERROR, "Invalid padding detected.");
-      return 0;
-    }
-  } else if (codes[3] == GRPC_BASE64_PAD_BYTE) {
-    decode_two_chars(codes, result, result_offset);
-  } else {
-    /* No padding. */
-    uint32_t packed = ((uint32_t)codes[0] << 18) | ((uint32_t)codes[1] << 12) |
-                      ((uint32_t)codes[2] << 6) | codes[3];
-    result[(*result_offset)++] = (unsigned char)(packed >> 16);
-    result[(*result_offset)++] = (unsigned char)(packed >> 8);
-    result[(*result_offset)++] = (unsigned char)(packed);
-  }
-  return 1;
-}
-
-gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
-                                      int url_safe) {
-  gpr_slice result = gpr_slice_malloc(b64_len);
-  unsigned char *current = GPR_SLICE_START_PTR(result);
-  size_t result_size = 0;
-  unsigned char codes[4];
-  size_t num_codes = 0;
-
-  while (b64_len--) {
-    unsigned char c = (unsigned char)(*b64++);
-    signed char code;
-    if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue;
-    if (url_safe) {
-      if (c == '+' || c == '/') {
-        gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c);
-        goto fail;
-      }
-      if (c == '-') {
-        c = '+';
-      } else if (c == '_') {
-        c = '/';
-      }
-    }
-    code = base64_bytes[c];
-    if (code == -1) {
-      if (c != '\r' && c != '\n') {
-        gpr_log(GPR_ERROR, "Invalid character %c", c);
-        goto fail;
-      }
-    } else {
-      codes[num_codes++] = (unsigned char)code;
-      if (num_codes == 4) {
-        if (!decode_group(codes, num_codes, current, &result_size)) goto fail;
-        num_codes = 0;
-      }
-    }
-  }
-
-  if (num_codes != 0 &&
-      !decode_group(codes, num_codes, current, &result_size)) {
-    goto fail;
-  }
-  GPR_SLICE_SET_LENGTH(result, result_size);
-  return result;
-
-fail:
-  gpr_slice_unref(result);
-  return gpr_empty_slice();
-}
diff --git a/src/core/lib/security/b64.h b/src/core/lib/security/b64.h
deleted file mode 100644
index c515e7a..0000000
--- a/src/core/lib/security/b64.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_B64_H
-#define GRPC_CORE_LIB_SECURITY_B64_H
-
-#include <grpc/support/slice.h>
-
-/* Encodes data using base64. It is the caller's responsability to free
-   the returned char * using gpr_free. Returns NULL on NULL input. */
-char *grpc_base64_encode(const void *data, size_t data_size, int url_safe,
-                         int multiline);
-
-/* Decodes data according to the base64 specification. Returns an empty
-   slice in case of failure. */
-gpr_slice grpc_base64_decode(const char *b64, int url_safe);
-
-/* Same as above except that the length is provided by the caller. */
-gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
-                                      int url_safe);
-
-#endif /* GRPC_CORE_LIB_SECURITY_B64_H */
diff --git a/src/core/lib/security/client_auth_filter.c b/src/core/lib/security/client_auth_filter.c
deleted file mode 100644
index ea50c85..0000000
--- a/src/core/lib/security/client_auth_filter.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/auth_filters.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/channel/channel_stack.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/security_connector.h"
-#include "src/core/lib/security/security_context.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/surface/call.h"
-#include "src/core/lib/transport/static_metadata.h"
-
-#define MAX_CREDENTIALS_METADATA_COUNT 4
-
-/* We can have a per-call credentials. */
-typedef struct {
-  grpc_call_credentials *creds;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
-  /* pollset{_set} bound to this call; if we need to make external
-     network requests, they should be done under a pollset added to this
-     pollset_set so that work can progress when this call wants work to progress
-  */
-  grpc_pops *pops;
-  grpc_transport_stream_op op;
-  uint8_t security_context_set;
-  grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
-  grpc_auth_metadata_context auth_md_context;
-} call_data;
-
-/* We can have a per-channel credentials. */
-typedef struct {
-  grpc_channel_security_connector *security_connector;
-  grpc_auth_context *auth_context;
-} channel_data;
-
-static void reset_auth_metadata_context(
-    grpc_auth_metadata_context *auth_md_context) {
-  if (auth_md_context->service_url != NULL) {
-    gpr_free((char *)auth_md_context->service_url);
-    auth_md_context->service_url = NULL;
-  }
-  if (auth_md_context->method_name != NULL) {
-    gpr_free((char *)auth_md_context->method_name);
-    auth_md_context->method_name = NULL;
-  }
-  GRPC_AUTH_CONTEXT_UNREF(
-      (grpc_auth_context *)auth_md_context->channel_auth_context,
-      "grpc_auth_metadata_context");
-  auth_md_context->channel_auth_context = NULL;
-}
-
-static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                            grpc_status_code status, const char *error_msg) {
-  call_data *calld = elem->call_data;
-  gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
-  grpc_transport_stream_op_add_cancellation(&calld->op, status);
-  grpc_call_next_op(exec_ctx, elem, &calld->op);
-}
-
-static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
-                                    grpc_credentials_md *md_elems,
-                                    size_t num_md,
-                                    grpc_credentials_status status) {
-  grpc_call_element *elem = (grpc_call_element *)user_data;
-  call_data *calld = elem->call_data;
-  grpc_transport_stream_op *op = &calld->op;
-  grpc_metadata_batch *mdb;
-  size_t i;
-  reset_auth_metadata_context(&calld->auth_md_context);
-  if (status != GRPC_CREDENTIALS_OK) {
-    bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
-                    "Credentials failed to get metadata.");
-    return;
-  }
-  GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
-  GPR_ASSERT(op->send_initial_metadata != NULL);
-  mdb = op->send_initial_metadata;
-  for (i = 0; i < num_md; i++) {
-    grpc_metadata_batch_add_tail(
-        mdb, &calld->md_links[i],
-        grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key),
-                                gpr_slice_ref(md_elems[i].value)));
-  }
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-void build_auth_metadata_context(grpc_security_connector *sc,
-                                 grpc_auth_context *auth_context,
-                                 call_data *calld) {
-  char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
-  char *last_slash = strrchr(service, '/');
-  char *method_name = NULL;
-  char *service_url = NULL;
-  reset_auth_metadata_context(&calld->auth_md_context);
-  if (last_slash == NULL) {
-    gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
-    service[0] = '\0';
-  } else if (last_slash == service) {
-    /* No service part in fully qualified method name: will just be "/". */
-    service[1] = '\0';
-  } else {
-    *last_slash = '\0';
-    method_name = gpr_strdup(last_slash + 1);
-  }
-  if (method_name == NULL) method_name = gpr_strdup("");
-  gpr_asprintf(&service_url, "%s://%s%s",
-               sc->url_scheme == NULL ? "" : sc->url_scheme,
-               grpc_mdstr_as_c_string(calld->host), service);
-  calld->auth_md_context.service_url = service_url;
-  calld->auth_md_context.method_name = method_name;
-  calld->auth_md_context.channel_auth_context =
-      GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
-  gpr_free(service);
-}
-
-static void send_security_metadata(grpc_exec_ctx *exec_ctx,
-                                   grpc_call_element *elem,
-                                   grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  grpc_client_security_context *ctx =
-      (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
-  grpc_call_credentials *channel_call_creds =
-      chand->security_connector->request_metadata_creds;
-  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);
-
-  if (channel_call_creds == NULL && !call_creds_has_md) {
-    /* Skip sending metadata altogether. */
-    grpc_call_next_op(exec_ctx, elem, op);
-    return;
-  }
-
-  if (channel_call_creds != NULL && call_creds_has_md) {
-    calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
-                                                          ctx->creds, NULL);
-    if (calld->creds == NULL) {
-      bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL,
-                      "Incompatible credentials set on channel and call.");
-      return;
-    }
-  } else {
-    calld->creds = grpc_call_credentials_ref(
-        call_creds_has_md ? ctx->creds : channel_call_creds);
-  }
-
-  build_auth_metadata_context(&chand->security_connector->base,
-                              chand->auth_context, calld);
-  calld->op = *op; /* Copy op (originates from the caller's stack). */
-  GPR_ASSERT(calld->pops != NULL);
-  grpc_call_credentials_get_request_metadata(
-      exec_ctx, calld->creds, calld->pops, calld->auth_md_context,
-      on_credentials_metadata, elem);
-}
-
-static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
-                            grpc_security_status status) {
-  grpc_call_element *elem = (grpc_call_element *)user_data;
-  call_data *calld = elem->call_data;
-
-  if (status == GRPC_SECURITY_OK) {
-    send_security_metadata(exec_ctx, elem, &calld->op);
-  } else {
-    char *error_msg;
-    gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
-                 grpc_mdstr_as_c_string(calld->host));
-    bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg);
-    gpr_free(error_msg);
-  }
-}
-
-/* Called either:
-     - in response to an API call (or similar) from above, to send something
-     - a network event (or similar) from below, to receive something
-   op contains type and call direction information, in addition to the data
-   that is being sent or received. */
-static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                    grpc_call_element *elem,
-                                    grpc_transport_stream_op *op) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  grpc_linked_mdelem *l;
-  grpc_client_security_context *sec_ctx = NULL;
-
-  if (calld->security_context_set == 0 &&
-      op->cancel_with_status == GRPC_STATUS_OK) {
-    calld->security_context_set = 1;
-    GPR_ASSERT(op->context);
-    if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
-      op->context[GRPC_CONTEXT_SECURITY].value =
-          grpc_client_security_context_create();
-      op->context[GRPC_CONTEXT_SECURITY].destroy =
-          grpc_client_security_context_destroy;
-    }
-    sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
-    GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
-    sec_ctx->auth_context =
-        GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter");
-  }
-
-  if (op->send_initial_metadata != NULL) {
-    for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) {
-      grpc_mdelem *md = l->md;
-      /* Pointer comparison is OK for md_elems created from the same context.
-       */
-      if (md->key == GRPC_MDSTR_AUTHORITY) {
-        if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
-        calld->host = GRPC_MDSTR_REF(md->value);
-      } else if (md->key == GRPC_MDSTR_PATH) {
-        if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
-        calld->method = GRPC_MDSTR_REF(md->value);
-      }
-    }
-    if (calld->host != NULL) {
-      const char *call_host = grpc_mdstr_as_c_string(calld->host);
-      calld->op = *op; /* Copy op (originates from the caller's stack). */
-      grpc_channel_security_connector_check_call_host(
-          exec_ctx, chand->security_connector, call_host, chand->auth_context,
-          on_host_checked, elem);
-      return; /* early exit */
-    }
-  }
-
-  /* pass control down the stack */
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
-  call_data *calld = elem->call_data;
-  memset(calld, 0, sizeof(*calld));
-}
-
-static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
-                                       grpc_call_element *elem,
-                                       grpc_pops *pops) {
-  call_data *calld = elem->call_data;
-  calld->pops = pops;
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                              void *ignored) {
-  call_data *calld = elem->call_data;
-  grpc_call_credentials_unref(calld->creds);
-  if (calld->host != NULL) {
-    GRPC_MDSTR_UNREF(calld->host);
-  }
-  if (calld->method != NULL) {
-    GRPC_MDSTR_UNREF(calld->method);
-  }
-  reset_auth_metadata_context(&calld->auth_md_context);
-}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  grpc_security_connector *sc =
-      grpc_find_security_connector_in_args(args->channel_args);
-  grpc_auth_context *auth_context =
-      grpc_find_auth_context_in_args(args->channel_args);
-
-  /* grab pointers to our data from the channel element */
-  channel_data *chand = elem->channel_data;
-
-  /* The first and the last filters tend to be implemented differently to
-     handle the case that there's no 'next' filter to call on the up or down
-     path */
-  GPR_ASSERT(!args->is_last);
-  GPR_ASSERT(sc != NULL);
-  GPR_ASSERT(auth_context != NULL);
-
-  /* initialize members */
-  chand->security_connector =
-      (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
-          sc, "client_auth_filter");
-  chand->auth_context =
-      GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  /* grab pointers to our data from the channel element */
-  channel_data *chand = elem->channel_data;
-  grpc_channel_security_connector *sc = chand->security_connector;
-  if (sc != NULL) {
-    GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
-  }
-  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
-}
-
-const grpc_channel_filter grpc_client_auth_filter = {auth_start_transport_op,
-                                                     grpc_channel_next_op,
-                                                     sizeof(call_data),
-                                                     init_call_elem,
-                                                     set_pollset_or_pollset_set,
-                                                     destroy_call_elem,
-                                                     sizeof(channel_data),
-                                                     init_channel_elem,
-                                                     destroy_channel_elem,
-                                                     grpc_call_next_get_peer,
-                                                     "client-auth"};
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
new file mode 100644
index 0000000..127b13e
--- /dev/null
+++ b/src/core/lib/security/context/security_context.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * Copyright 2015, 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 <string.h>
+
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/call.h"
+
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+/* --- grpc_call --- */
+
+grpc_call_error grpc_call_set_credentials(grpc_call *call,
+                                          grpc_call_credentials *creds) {
+  grpc_client_security_context *ctx = NULL;
+  GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
+                 (call, creds));
+  if (!grpc_call_is_client(call)) {
+    gpr_log(GPR_ERROR, "Method is client-side only.");
+    return GRPC_CALL_ERROR_NOT_ON_SERVER;
+  }
+  ctx = (grpc_client_security_context *)grpc_call_context_get(
+      call, GRPC_CONTEXT_SECURITY);
+  if (ctx == NULL) {
+    ctx = grpc_client_security_context_create();
+    ctx->creds = grpc_call_credentials_ref(creds);
+    grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
+                          grpc_client_security_context_destroy);
+  } else {
+    grpc_call_credentials_unref(ctx->creds);
+    ctx->creds = grpc_call_credentials_ref(creds);
+  }
+  return GRPC_CALL_OK;
+}
+
+grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
+  void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
+  GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call));
+  if (sec_ctx == NULL) return NULL;
+  return grpc_call_is_client(call)
+             ? GRPC_AUTH_CONTEXT_REF(
+                   ((grpc_client_security_context *)sec_ctx)->auth_context,
+                   "grpc_call_auth_context client")
+             : GRPC_AUTH_CONTEXT_REF(
+                   ((grpc_server_security_context *)sec_ctx)->auth_context,
+                   "grpc_call_auth_context server");
+}
+
+void grpc_auth_context_release(grpc_auth_context *context) {
+  GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context));
+  GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref");
+}
+
+/* --- grpc_client_security_context --- */
+
+grpc_client_security_context *grpc_client_security_context_create(void) {
+  grpc_client_security_context *ctx =
+      gpr_malloc(sizeof(grpc_client_security_context));
+  memset(ctx, 0, sizeof(grpc_client_security_context));
+  return ctx;
+}
+
+void grpc_client_security_context_destroy(void *ctx) {
+  grpc_client_security_context *c = (grpc_client_security_context *)ctx;
+  grpc_call_credentials_unref(c->creds);
+  GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context");
+  gpr_free(ctx);
+}
+
+/* --- grpc_server_security_context --- */
+
+grpc_server_security_context *grpc_server_security_context_create(void) {
+  grpc_server_security_context *ctx =
+      gpr_malloc(sizeof(grpc_server_security_context));
+  memset(ctx, 0, sizeof(grpc_server_security_context));
+  return ctx;
+}
+
+void grpc_server_security_context_destroy(void *ctx) {
+  grpc_server_security_context *c = (grpc_server_security_context *)ctx;
+  GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context");
+  gpr_free(ctx);
+}
+
+/* --- grpc_auth_context --- */
+
+static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
+
+grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
+  grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
+  memset(ctx, 0, sizeof(grpc_auth_context));
+  gpr_ref_init(&ctx->refcount, 1);
+  if (chained != NULL) {
+    ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
+    ctx->peer_identity_property_name =
+        ctx->chained->peer_identity_property_name;
+  }
+  return ctx;
+}
+
+#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
+grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx,
+                                         const char *file, int line,
+                                         const char *reason) {
+  if (ctx == NULL) return NULL;
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "AUTH_CONTEXT:%p   ref %d -> %d %s", ctx, (int)ctx->refcount.count,
+          (int)ctx->refcount.count + 1, reason);
+#else
+grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) {
+  if (ctx == NULL) return NULL;
+#endif
+  gpr_ref(&ctx->refcount);
+  return ctx;
+}
+
+#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
+void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line,
+                             const char *reason) {
+  if (ctx == NULL) return;
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count,
+          (int)ctx->refcount.count - 1, reason);
+#else
+void grpc_auth_context_unref(grpc_auth_context *ctx) {
+  if (ctx == NULL) return;
+#endif
+  if (gpr_unref(&ctx->refcount)) {
+    size_t i;
+    GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained");
+    if (ctx->properties.array != NULL) {
+      for (i = 0; i < ctx->properties.count; i++) {
+        grpc_auth_property_reset(&ctx->properties.array[i]);
+      }
+      gpr_free(ctx->properties.array);
+    }
+    gpr_free(ctx);
+  }
+}
+
+const char *grpc_auth_context_peer_identity_property_name(
+    const grpc_auth_context *ctx) {
+  GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1,
+                 (ctx));
+  return ctx->peer_identity_property_name;
+}
+
+int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
+                                                      const char *name) {
+  grpc_auth_property_iterator it =
+      grpc_auth_context_find_properties_by_name(ctx, name);
+  const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
+  GRPC_API_TRACE(
+      "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2,
+      (ctx, name));
+  if (prop == NULL) {
+    gpr_log(GPR_ERROR, "Property name %s not found in auth context.",
+            name != NULL ? name : "NULL");
+    return 0;
+  }
+  ctx->peer_identity_property_name = prop->name;
+  return 1;
+}
+
+int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) {
+  GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx));
+  return ctx->peer_identity_property_name == NULL ? 0 : 1;
+}
+
+grpc_auth_property_iterator grpc_auth_context_property_iterator(
+    const grpc_auth_context *ctx) {
+  grpc_auth_property_iterator it = empty_iterator;
+  GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx));
+  if (ctx == NULL) return it;
+  it.ctx = ctx;
+  return it;
+}
+
+const grpc_auth_property *grpc_auth_property_iterator_next(
+    grpc_auth_property_iterator *it) {
+  GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it));
+  if (it == NULL || it->ctx == NULL) return NULL;
+  while (it->index == it->ctx->properties.count) {
+    if (it->ctx->chained == NULL) return NULL;
+    it->ctx = it->ctx->chained;
+    it->index = 0;
+  }
+  if (it->name == NULL) {
+    return &it->ctx->properties.array[it->index++];
+  } else {
+    while (it->index < it->ctx->properties.count) {
+      const grpc_auth_property *prop = &it->ctx->properties.array[it->index++];
+      GPR_ASSERT(prop->name != NULL);
+      if (strcmp(it->name, prop->name) == 0) {
+        return prop;
+      }
+    }
+    /* We could not find the name, try another round. */
+    return grpc_auth_property_iterator_next(it);
+  }
+}
+
+grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
+    const grpc_auth_context *ctx, const char *name) {
+  grpc_auth_property_iterator it = empty_iterator;
+  GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)",
+                 2, (ctx, name));
+  if (ctx == NULL || name == NULL) return empty_iterator;
+  it.ctx = ctx;
+  it.name = name;
+  return it;
+}
+
+grpc_auth_property_iterator grpc_auth_context_peer_identity(
+    const grpc_auth_context *ctx) {
+  GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx));
+  if (ctx == NULL) return empty_iterator;
+  return grpc_auth_context_find_properties_by_name(
+      ctx, ctx->peer_identity_property_name);
+}
+
+static void ensure_auth_context_capacity(grpc_auth_context *ctx) {
+  if (ctx->properties.count == ctx->properties.capacity) {
+    ctx->properties.capacity =
+        GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2);
+    ctx->properties.array =
+        gpr_realloc(ctx->properties.array,
+                    ctx->properties.capacity * sizeof(grpc_auth_property));
+  }
+}
+
+void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
+                                    const char *value, size_t value_length) {
+  grpc_auth_property *prop;
+  GRPC_API_TRACE(
+      "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, "
+      "value_length=%lu)",
+      6, (ctx, name, (int)value_length, (int)value_length, value,
+          (unsigned long)value_length));
+  ensure_auth_context_capacity(ctx);
+  prop = &ctx->properties.array[ctx->properties.count++];
+  prop->name = gpr_strdup(name);
+  prop->value = gpr_malloc(value_length + 1);
+  memcpy(prop->value, value, value_length);
+  prop->value[value_length] = '\0';
+  prop->value_length = value_length;
+}
+
+void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
+                                            const char *name,
+                                            const char *value) {
+  grpc_auth_property *prop;
+  GRPC_API_TRACE(
+      "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3,
+      (ctx, name, value));
+  ensure_auth_context_capacity(ctx);
+  prop = &ctx->properties.array[ctx->properties.count++];
+  prop->name = gpr_strdup(name);
+  prop->value = gpr_strdup(value);
+  prop->value_length = strlen(value);
+}
+
+void grpc_auth_property_reset(grpc_auth_property *property) {
+  gpr_free(property->name);
+  gpr_free(property->value);
+  memset(property, 0, sizeof(grpc_auth_property));
+}
+
+static void auth_context_pointer_arg_destroy(void *p) {
+  GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg");
+}
+
+static void *auth_context_pointer_arg_copy(void *p) {
+  return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg");
+}
+
+static int auth_context_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
+
+static const grpc_arg_pointer_vtable auth_context_pointer_vtable = {
+    auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy,
+    auth_context_pointer_cmp};
+
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) {
+  grpc_arg arg;
+  memset(&arg, 0, sizeof(grpc_arg));
+  arg.type = GRPC_ARG_POINTER;
+  arg.key = GRPC_AUTH_CONTEXT_ARG;
+  arg.value.pointer.p = p;
+  arg.value.pointer.vtable = &auth_context_pointer_vtable;
+  return arg;
+}
+
+grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg) {
+  if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL;
+  if (arg->type != GRPC_ARG_POINTER) {
+    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+            GRPC_AUTH_CONTEXT_ARG);
+    return NULL;
+  }
+  return arg->value.pointer.p;
+}
+
+grpc_auth_context *grpc_find_auth_context_in_args(
+    const grpc_channel_args *args) {
+  size_t i;
+  if (args == NULL) return NULL;
+  for (i = 0; i < args->num_args; i++) {
+    grpc_auth_context *p = grpc_auth_context_from_arg(&args->args[i]);
+    if (p != NULL) return p;
+  }
+  return NULL;
+}
diff --git a/src/core/lib/security/context/security_context.h b/src/core/lib/security/context/security_context.h
new file mode 100644
index 0000000..ef0c06b
--- /dev/null
+++ b/src/core/lib/security/context/security_context.h
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_CONTEXT_SECURITY_CONTEXT_H
+#define GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H
+
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/security/credentials/credentials.h"
+
+/* --- grpc_auth_context ---
+
+   High level authentication context object. Can optionally be chained. */
+
+/* Property names are always NULL terminated. */
+
+typedef struct {
+  grpc_auth_property *array;
+  size_t count;
+  size_t capacity;
+} grpc_auth_property_array;
+
+struct grpc_auth_context {
+  struct grpc_auth_context *chained;
+  grpc_auth_property_array properties;
+  gpr_refcount refcount;
+  const char *peer_identity_property_name;
+  grpc_pollset *pollset;
+};
+
+/* Creation. */
+grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained);
+
+/* Refcounting. */
+#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
+#define GRPC_AUTH_CONTEXT_REF(p, r) \
+  grpc_auth_context_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_AUTH_CONTEXT_UNREF(p, r) \
+  grpc_auth_context_unref((p), __FILE__, __LINE__, (r))
+grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy,
+                                         const char *file, int line,
+                                         const char *reason);
+void grpc_auth_context_unref(grpc_auth_context *policy, const char *file,
+                             int line, const char *reason);
+#else
+#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p))
+#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p))
+grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy);
+void grpc_auth_context_unref(grpc_auth_context *policy);
+#endif
+
+void grpc_auth_property_reset(grpc_auth_property *property);
+
+/* --- grpc_client_security_context ---
+
+   Internal client-side security context. */
+
+typedef struct {
+  grpc_call_credentials *creds;
+  grpc_auth_context *auth_context;
+} grpc_client_security_context;
+
+grpc_client_security_context *grpc_client_security_context_create(void);
+void grpc_client_security_context_destroy(void *ctx);
+
+/* --- grpc_server_security_context ---
+
+   Internal server-side security context. */
+
+typedef struct {
+  grpc_auth_context *auth_context;
+} grpc_server_security_context;
+
+grpc_server_security_context *grpc_server_security_context_create(void);
+void grpc_server_security_context_destroy(void *ctx);
+
+/* --- Channel args for auth context --- */
+#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context"
+
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c);
+grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
+grpc_auth_context *grpc_find_auth_context_in_args(
+    const grpc_channel_args *args);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H */
diff --git a/src/core/lib/security/credentials.c b/src/core/lib/security/credentials.c
deleted file mode 100644
index 43c061a..0000000
--- a/src/core/lib/security/credentials.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/credentials.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/channel/http_client_filter.h"
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/http/parser.h"
-#include "src/core/lib/iomgr/executor.h"
-#include "src/core/lib/json/json.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/surface/api_trace.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-/* -- Common. -- */
-
-struct grpc_credentials_metadata_request {
-  grpc_call_credentials *creds;
-  grpc_credentials_metadata_cb cb;
-  void *user_data;
-};
-
-static grpc_credentials_metadata_request *
-grpc_credentials_metadata_request_create(grpc_call_credentials *creds,
-                                         grpc_credentials_metadata_cb cb,
-                                         void *user_data) {
-  grpc_credentials_metadata_request *r =
-      gpr_malloc(sizeof(grpc_credentials_metadata_request));
-  r->creds = grpc_call_credentials_ref(creds);
-  r->cb = cb;
-  r->user_data = user_data;
-  return r;
-}
-
-static void grpc_credentials_metadata_request_destroy(
-    grpc_credentials_metadata_request *r) {
-  grpc_call_credentials_unref(r->creds);
-  gpr_free(r);
-}
-
-grpc_channel_credentials *grpc_channel_credentials_ref(
-    grpc_channel_credentials *creds) {
-  if (creds == NULL) return NULL;
-  gpr_ref(&creds->refcount);
-  return creds;
-}
-
-void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
-  if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) {
-    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
-    gpr_free(creds);
-  }
-}
-
-void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
-  GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
-  grpc_channel_credentials_unref(creds);
-}
-
-grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
-  if (creds == NULL) return NULL;
-  gpr_ref(&creds->refcount);
-  return creds;
-}
-
-void grpc_call_credentials_unref(grpc_call_credentials *creds) {
-  if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) {
-    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
-    gpr_free(creds);
-  }
-}
-
-void grpc_call_credentials_release(grpc_call_credentials *creds) {
-  GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
-  grpc_call_credentials_unref(creds);
-}
-
-void grpc_call_credentials_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
-    void *user_data) {
-  if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
-    if (cb != NULL) {
-      cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
-    }
-    return;
-  }
-  creds->vtable->get_request_metadata(exec_ctx, creds, pops, context, cb,
-                                      user_data);
-}
-
-grpc_security_status grpc_channel_credentials_create_security_connector(
-    grpc_channel_credentials *channel_creds, const char *target,
-    const grpc_channel_args *args, grpc_channel_security_connector **sc,
-    grpc_channel_args **new_args) {
-  *new_args = NULL;
-  if (channel_creds == NULL) {
-    return GRPC_SECURITY_ERROR;
-  }
-  GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
-  return channel_creds->vtable->create_security_connector(
-      channel_creds, NULL, target, args, sc, new_args);
-}
-
-grpc_server_credentials *grpc_server_credentials_ref(
-    grpc_server_credentials *creds) {
-  if (creds == NULL) return NULL;
-  gpr_ref(&creds->refcount);
-  return creds;
-}
-
-void grpc_server_credentials_unref(grpc_server_credentials *creds) {
-  if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) {
-    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
-    if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
-      creds->processor.destroy(creds->processor.state);
-    }
-    gpr_free(creds);
-  }
-}
-
-void grpc_server_credentials_release(grpc_server_credentials *creds) {
-  GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds));
-  grpc_server_credentials_unref(creds);
-}
-
-grpc_security_status grpc_server_credentials_create_security_connector(
-    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
-  if (creds == NULL || creds->vtable->create_security_connector == NULL) {
-    gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
-    return GRPC_SECURITY_ERROR;
-  }
-  return creds->vtable->create_security_connector(creds, sc);
-}
-
-void grpc_server_credentials_set_auth_metadata_processor(
-    grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
-  GRPC_API_TRACE(
-      "grpc_server_credentials_set_auth_metadata_processor("
-      "creds=%p, "
-      "processor=grpc_auth_metadata_processor { process: %p, state: %p })",
-      3, (creds, (void *)(intptr_t)processor.process, processor.state));
-  if (creds == NULL) return;
-  if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
-    creds->processor.destroy(creds->processor.state);
-  }
-  creds->processor = processor;
-}
-
-static void server_credentials_pointer_arg_destroy(void *p) {
-  grpc_server_credentials_unref(p);
-}
-
-static void *server_credentials_pointer_arg_copy(void *p) {
-  return grpc_server_credentials_ref(p);
-}
-
-static int server_credentials_pointer_cmp(void *a, void *b) {
-  return GPR_ICMP(a, b);
-}
-
-static const grpc_arg_pointer_vtable cred_ptr_vtable = {
-    server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy,
-    server_credentials_pointer_cmp};
-
-grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
-  grpc_arg arg;
-  memset(&arg, 0, sizeof(grpc_arg));
-  arg.type = GRPC_ARG_POINTER;
-  arg.key = GRPC_SERVER_CREDENTIALS_ARG;
-  arg.value.pointer.p = p;
-  arg.value.pointer.vtable = &cred_ptr_vtable;
-  return arg;
-}
-
-grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
-  if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
-  if (arg->type != GRPC_ARG_POINTER) {
-    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
-            GRPC_SERVER_CREDENTIALS_ARG);
-    return NULL;
-  }
-  return arg->value.pointer.p;
-}
-
-grpc_server_credentials *grpc_find_server_credentials_in_args(
-    const grpc_channel_args *args) {
-  size_t i;
-  if (args == NULL) return NULL;
-  for (i = 0; i < args->num_args; i++) {
-    grpc_server_credentials *p =
-        grpc_server_credentials_from_arg(&args->args[i]);
-    if (p != NULL) return p;
-  }
-  return NULL;
-}
-
-/* -- Ssl credentials. -- */
-
-static void ssl_destruct(grpc_channel_credentials *creds) {
-  grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
-  if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
-  if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
-  if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
-}
-
-static void ssl_server_destruct(grpc_server_credentials *creds) {
-  grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->config.num_key_cert_pairs; i++) {
-    if (c->config.pem_private_keys[i] != NULL) {
-      gpr_free(c->config.pem_private_keys[i]);
-    }
-    if (c->config.pem_cert_chains[i] != NULL) {
-      gpr_free(c->config.pem_cert_chains[i]);
-    }
-  }
-  if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
-  if (c->config.pem_private_keys_sizes != NULL) {
-    gpr_free(c->config.pem_private_keys_sizes);
-  }
-  if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
-  if (c->config.pem_cert_chains_sizes != NULL) {
-    gpr_free(c->config.pem_cert_chains_sizes);
-  }
-  if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
-}
-
-static grpc_security_status ssl_create_security_connector(
-    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
-    const char *target, const grpc_channel_args *args,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
-  grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
-  grpc_security_status status = GRPC_SECURITY_OK;
-  size_t i = 0;
-  const char *overridden_target_name = NULL;
-  grpc_arg new_arg;
-
-  for (i = 0; args && i < args->num_args; i++) {
-    grpc_arg *arg = &args->args[i];
-    if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
-        arg->type == GRPC_ARG_STRING) {
-      overridden_target_name = arg->value.string;
-      break;
-    }
-  }
-  status = grpc_ssl_channel_security_connector_create(
-      call_creds, &c->config, target, overridden_target_name, sc);
-  if (status != GRPC_SECURITY_OK) {
-    return status;
-  }
-  new_arg.type = GRPC_ARG_STRING;
-  new_arg.key = GRPC_ARG_HTTP2_SCHEME;
-  new_arg.value.string = "https";
-  *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
-  return status;
-}
-
-static grpc_security_status ssl_server_create_security_connector(
-    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
-  grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
-  return grpc_ssl_server_security_connector_create(&c->config, sc);
-}
-
-static grpc_channel_credentials_vtable ssl_vtable = {
-    ssl_destruct, ssl_create_security_connector};
-
-static grpc_server_credentials_vtable ssl_server_vtable = {
-    ssl_server_destruct, ssl_server_create_security_connector};
-
-static void ssl_copy_key_material(const char *input, unsigned char **output,
-                                  size_t *output_size) {
-  *output_size = strlen(input);
-  *output = gpr_malloc(*output_size);
-  memcpy(*output, input, *output_size);
-}
-
-static void ssl_build_config(const char *pem_root_certs,
-                             grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
-                             grpc_ssl_config *config) {
-  if (pem_root_certs != NULL) {
-    ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
-                          &config->pem_root_certs_size);
-  }
-  if (pem_key_cert_pair != NULL) {
-    GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
-    GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
-    ssl_copy_key_material(pem_key_cert_pair->private_key,
-                          &config->pem_private_key,
-                          &config->pem_private_key_size);
-    ssl_copy_key_material(pem_key_cert_pair->cert_chain,
-                          &config->pem_cert_chain,
-                          &config->pem_cert_chain_size);
-  }
-}
-
-static void ssl_build_server_config(
-    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
-    size_t num_key_cert_pairs,
-    grpc_ssl_client_certificate_request_type client_certificate_request,
-    grpc_ssl_server_config *config) {
-  size_t i;
-  config->client_certificate_request = client_certificate_request;
-  if (pem_root_certs != NULL) {
-    ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
-                          &config->pem_root_certs_size);
-  }
-  if (num_key_cert_pairs > 0) {
-    GPR_ASSERT(pem_key_cert_pairs != NULL);
-    config->pem_private_keys =
-        gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
-    config->pem_cert_chains =
-        gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
-    config->pem_private_keys_sizes =
-        gpr_malloc(num_key_cert_pairs * sizeof(size_t));
-    config->pem_cert_chains_sizes =
-        gpr_malloc(num_key_cert_pairs * sizeof(size_t));
-  }
-  config->num_key_cert_pairs = num_key_cert_pairs;
-  for (i = 0; i < num_key_cert_pairs; i++) {
-    GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
-    GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
-    ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
-                          &config->pem_private_keys[i],
-                          &config->pem_private_keys_sizes[i]);
-    ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
-                          &config->pem_cert_chains[i],
-                          &config->pem_cert_chains_sizes[i]);
-  }
-}
-
-grpc_channel_credentials *grpc_ssl_credentials_create(
-    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
-    void *reserved) {
-  grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
-  GRPC_API_TRACE(
-      "grpc_ssl_credentials_create(pem_root_certs=%s, "
-      "pem_key_cert_pair=%p, "
-      "reserved=%p)",
-      3, (pem_root_certs, pem_key_cert_pair, reserved));
-  GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_credentials));
-  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
-  c->base.vtable = &ssl_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
-  return &c->base;
-}
-
-grpc_server_credentials *grpc_ssl_server_credentials_create(
-    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
-    size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
-  return grpc_ssl_server_credentials_create_ex(
-      pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
-      force_client_auth
-          ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
-          : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
-      reserved);
-}
-
-grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
-    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
-    size_t num_key_cert_pairs,
-    grpc_ssl_client_certificate_request_type client_certificate_request,
-    void *reserved) {
-  grpc_ssl_server_credentials *c =
-      gpr_malloc(sizeof(grpc_ssl_server_credentials));
-  GRPC_API_TRACE(
-      "grpc_ssl_server_credentials_create_ex("
-      "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
-      "client_certificate_request=%d, reserved=%p)",
-      5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
-          client_certificate_request, reserved));
-  GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_server_credentials));
-  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.vtable = &ssl_server_vtable;
-  ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
-                          num_key_cert_pairs, client_certificate_request,
-                          &c->config);
-  return &c->base;
-}
-
-/* -- Jwt credentials -- */
-
-static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
-  if (c->cached.jwt_md != NULL) {
-    grpc_credentials_md_store_unref(c->cached.jwt_md);
-    c->cached.jwt_md = NULL;
-  }
-  if (c->cached.service_url != NULL) {
-    gpr_free(c->cached.service_url);
-    c->cached.service_url = NULL;
-  }
-  c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
-}
-
-static void jwt_destruct(grpc_call_credentials *creds) {
-  grpc_service_account_jwt_access_credentials *c =
-      (grpc_service_account_jwt_access_credentials *)creds;
-  grpc_auth_json_key_destruct(&c->key);
-  jwt_reset_cache(c);
-  gpr_mu_destroy(&c->cache_mu);
-}
-
-static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                     grpc_call_credentials *creds,
-                                     grpc_pops *pops,
-                                     grpc_auth_metadata_context context,
-                                     grpc_credentials_metadata_cb cb,
-                                     void *user_data) {
-  grpc_service_account_jwt_access_credentials *c =
-      (grpc_service_account_jwt_access_credentials *)creds;
-  gpr_timespec refresh_threshold = gpr_time_from_seconds(
-      GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
-
-  /* See if we can return a cached jwt. */
-  grpc_credentials_md_store *jwt_md = NULL;
-  {
-    gpr_mu_lock(&c->cache_mu);
-    if (c->cached.service_url != NULL &&
-        strcmp(c->cached.service_url, context.service_url) == 0 &&
-        c->cached.jwt_md != NULL &&
-        (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
-                                   gpr_now(GPR_CLOCK_REALTIME)),
-                      refresh_threshold) > 0)) {
-      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
-    }
-    gpr_mu_unlock(&c->cache_mu);
-  }
-
-  if (jwt_md == NULL) {
-    char *jwt = NULL;
-    /* Generate a new jwt. */
-    gpr_mu_lock(&c->cache_mu);
-    jwt_reset_cache(c);
-    jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
-                                   c->jwt_lifetime, NULL);
-    if (jwt != NULL) {
-      char *md_value;
-      gpr_asprintf(&md_value, "Bearer %s", jwt);
-      gpr_free(jwt);
-      c->cached.jwt_expiration =
-          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
-      c->cached.service_url = gpr_strdup(context.service_url);
-      c->cached.jwt_md = grpc_credentials_md_store_create(1);
-      grpc_credentials_md_store_add_cstrings(
-          c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
-      gpr_free(md_value);
-      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
-    }
-    gpr_mu_unlock(&c->cache_mu);
-  }
-
-  if (jwt_md != NULL) {
-    cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
-       GRPC_CREDENTIALS_OK);
-    grpc_credentials_md_store_unref(jwt_md);
-  } else {
-    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
-  }
-}
-
-static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
-                                                  jwt_get_request_metadata};
-
-grpc_call_credentials *
-grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
-    grpc_auth_json_key key, gpr_timespec token_lifetime) {
-  grpc_service_account_jwt_access_credentials *c;
-  if (!grpc_auth_json_key_is_valid(&key)) {
-    gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
-    return NULL;
-  }
-  c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
-  memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.vtable = &jwt_vtable;
-  c->key = key;
-  c->jwt_lifetime = token_lifetime;
-  gpr_mu_init(&c->cache_mu);
-  jwt_reset_cache(c);
-  return &c->base;
-}
-
-grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
-    const char *json_key, gpr_timespec token_lifetime, void *reserved) {
-  GRPC_API_TRACE(
-      "grpc_service_account_jwt_access_credentials_create("
-      "json_key=%s, "
-      "token_lifetime="
-      "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      5,
-      (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec,
-       (int)token_lifetime.clock_type, reserved));
-  GPR_ASSERT(reserved == NULL);
-  return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
-      grpc_auth_json_key_create_from_string(json_key), token_lifetime);
-}
-
-/* -- Oauth2TokenFetcher credentials -- */
-
-static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
-  grpc_oauth2_token_fetcher_credentials *c =
-      (grpc_oauth2_token_fetcher_credentials *)creds;
-  grpc_credentials_md_store_unref(c->access_token_md);
-  gpr_mu_destroy(&c->mu);
-  grpc_httpcli_context_destroy(&c->httpcli_context);
-}
-
-grpc_credentials_status
-grpc_oauth2_token_fetcher_credentials_parse_server_response(
-    const grpc_http_response *response, grpc_credentials_md_store **token_md,
-    gpr_timespec *token_lifetime) {
-  char *null_terminated_body = NULL;
-  char *new_access_token = NULL;
-  grpc_credentials_status status = GRPC_CREDENTIALS_OK;
-  grpc_json *json = NULL;
-
-  if (response == NULL) {
-    gpr_log(GPR_ERROR, "Received NULL response.");
-    status = GRPC_CREDENTIALS_ERROR;
-    goto end;
-  }
-
-  if (response->body_length > 0) {
-    null_terminated_body = gpr_malloc(response->body_length + 1);
-    null_terminated_body[response->body_length] = '\0';
-    memcpy(null_terminated_body, response->body, response->body_length);
-  }
-
-  if (response->status != 200) {
-    gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
-            response->status,
-            null_terminated_body != NULL ? null_terminated_body : "");
-    status = GRPC_CREDENTIALS_ERROR;
-    goto end;
-  } else {
-    grpc_json *access_token = NULL;
-    grpc_json *token_type = NULL;
-    grpc_json *expires_in = NULL;
-    grpc_json *ptr;
-    json = grpc_json_parse_string(null_terminated_body);
-    if (json == NULL) {
-      gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
-      status = GRPC_CREDENTIALS_ERROR;
-      goto end;
-    }
-    if (json->type != GRPC_JSON_OBJECT) {
-      gpr_log(GPR_ERROR, "Response should be a JSON object");
-      status = GRPC_CREDENTIALS_ERROR;
-      goto end;
-    }
-    for (ptr = json->child; ptr; ptr = ptr->next) {
-      if (strcmp(ptr->key, "access_token") == 0) {
-        access_token = ptr;
-      } else if (strcmp(ptr->key, "token_type") == 0) {
-        token_type = ptr;
-      } else if (strcmp(ptr->key, "expires_in") == 0) {
-        expires_in = ptr;
-      }
-    }
-    if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
-      gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
-      status = GRPC_CREDENTIALS_ERROR;
-      goto end;
-    }
-    if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
-      gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
-      status = GRPC_CREDENTIALS_ERROR;
-      goto end;
-    }
-    if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
-      gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
-      status = GRPC_CREDENTIALS_ERROR;
-      goto end;
-    }
-    gpr_asprintf(&new_access_token, "%s %s", token_type->value,
-                 access_token->value);
-    token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
-    token_lifetime->tv_nsec = 0;
-    token_lifetime->clock_type = GPR_TIMESPAN;
-    if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
-    *token_md = grpc_credentials_md_store_create(1);
-    grpc_credentials_md_store_add_cstrings(
-        *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
-    status = GRPC_CREDENTIALS_OK;
-  }
-
-end:
-  if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
-    grpc_credentials_md_store_unref(*token_md);
-    *token_md = NULL;
-  }
-  if (null_terminated_body != NULL) gpr_free(null_terminated_body);
-  if (new_access_token != NULL) gpr_free(new_access_token);
-  if (json != NULL) grpc_json_destroy(json);
-  return status;
-}
-
-static void on_oauth2_token_fetcher_http_response(
-    grpc_exec_ctx *exec_ctx, void *user_data,
-    const grpc_http_response *response) {
-  grpc_credentials_metadata_request *r =
-      (grpc_credentials_metadata_request *)user_data;
-  grpc_oauth2_token_fetcher_credentials *c =
-      (grpc_oauth2_token_fetcher_credentials *)r->creds;
-  gpr_timespec token_lifetime;
-  grpc_credentials_status status;
-
-  gpr_mu_lock(&c->mu);
-  status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
-      response, &c->access_token_md, &token_lifetime);
-  if (status == GRPC_CREDENTIALS_OK) {
-    c->token_expiration =
-        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
-    r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
-          c->access_token_md->num_entries, status);
-  } else {
-    c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
-    r->cb(exec_ctx, r->user_data, NULL, 0, status);
-  }
-  gpr_mu_unlock(&c->mu);
-  grpc_credentials_metadata_request_destroy(r);
-}
-
-static void oauth2_token_fetcher_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
-    void *user_data) {
-  grpc_oauth2_token_fetcher_credentials *c =
-      (grpc_oauth2_token_fetcher_credentials *)creds;
-  gpr_timespec refresh_threshold = gpr_time_from_seconds(
-      GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
-  grpc_credentials_md_store *cached_access_token_md = NULL;
-  {
-    gpr_mu_lock(&c->mu);
-    if (c->access_token_md != NULL &&
-        (gpr_time_cmp(
-             gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
-             refresh_threshold) > 0)) {
-      cached_access_token_md =
-          grpc_credentials_md_store_ref(c->access_token_md);
-    }
-    gpr_mu_unlock(&c->mu);
-  }
-  if (cached_access_token_md != NULL) {
-    cb(exec_ctx, user_data, cached_access_token_md->entries,
-       cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
-    grpc_credentials_md_store_unref(cached_access_token_md);
-  } else {
-    c->fetch_func(
-        exec_ctx,
-        grpc_credentials_metadata_request_create(creds, cb, user_data),
-        &c->httpcli_context, pops, on_oauth2_token_fetcher_http_response,
-        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
-  }
-}
-
-static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
-                                      grpc_fetch_oauth2_func fetch_func) {
-  memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
-  gpr_ref_init(&c->base.refcount, 1);
-  gpr_mu_init(&c->mu);
-  c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
-  c->fetch_func = fetch_func;
-  grpc_httpcli_context_init(&c->httpcli_context);
-}
-
-/* -- GoogleComputeEngine credentials. -- */
-
-static grpc_call_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
-
-static void compute_engine_fetch_oauth2(
-    grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
-    grpc_httpcli_context *httpcli_context, grpc_pops *pops,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
-  grpc_http_header header = {"Metadata-Flavor", "Google"};
-  grpc_httpcli_request request;
-  memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
-  request.http.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
-  request.http.hdr_count = 1;
-  request.http.hdrs = &header;
-  grpc_httpcli_get(exec_ctx, httpcli_context, pops, &request, deadline,
-                   response_cb, metadata_req);
-}
-
-grpc_call_credentials *grpc_google_compute_engine_credentials_create(
-    void *reserved) {
-  grpc_oauth2_token_fetcher_credentials *c =
-      gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
-  GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1,
-                 (reserved));
-  GPR_ASSERT(reserved == NULL);
-  init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
-  c->base.vtable = &compute_engine_vtable;
-  return &c->base;
-}
-
-/* -- GoogleRefreshToken credentials. -- */
-
-static void refresh_token_destruct(grpc_call_credentials *creds) {
-  grpc_google_refresh_token_credentials *c =
-      (grpc_google_refresh_token_credentials *)creds;
-  grpc_auth_refresh_token_destruct(&c->refresh_token);
-  oauth2_token_fetcher_destruct(&c->base.base);
-}
-
-static grpc_call_credentials_vtable refresh_token_vtable = {
-    refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
-
-static void refresh_token_fetch_oauth2(
-    grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
-    grpc_httpcli_context *httpcli_context, grpc_pops *pops,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
-  grpc_google_refresh_token_credentials *c =
-      (grpc_google_refresh_token_credentials *)metadata_req->creds;
-  grpc_http_header header = {"Content-Type",
-                             "application/x-www-form-urlencoded"};
-  grpc_httpcli_request request;
-  char *body = NULL;
-  gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
-               c->refresh_token.client_id, c->refresh_token.client_secret,
-               c->refresh_token.refresh_token);
-  memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
-  request.http.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
-  request.http.hdr_count = 1;
-  request.http.hdrs = &header;
-  request.handshaker = &grpc_httpcli_ssl;
-  grpc_httpcli_post(exec_ctx, httpcli_context, pops, &request, body,
-                    strlen(body), deadline, response_cb, metadata_req);
-  gpr_free(body);
-}
-
-grpc_call_credentials *
-grpc_refresh_token_credentials_create_from_auth_refresh_token(
-    grpc_auth_refresh_token refresh_token) {
-  grpc_google_refresh_token_credentials *c;
-  if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
-    gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
-    return NULL;
-  }
-  c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
-  memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
-  init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
-  c->base.base.vtable = &refresh_token_vtable;
-  c->refresh_token = refresh_token;
-  return &c->base.base;
-}
-
-grpc_call_credentials *grpc_google_refresh_token_credentials_create(
-    const char *json_refresh_token, void *reserved) {
-  GRPC_API_TRACE(
-      "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
-      "reserved=%p)",
-      2, (json_refresh_token, reserved));
-  GPR_ASSERT(reserved == NULL);
-  return grpc_refresh_token_credentials_create_from_auth_refresh_token(
-      grpc_auth_refresh_token_create_from_string(json_refresh_token));
-}
-
-/* -- Metadata-only credentials. -- */
-
-static void md_only_test_destruct(grpc_call_credentials *creds) {
-  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
-  grpc_credentials_md_store_unref(c->md_store);
-}
-
-static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
-                                          void *user_data, bool success) {
-  grpc_credentials_metadata_request *r =
-      (grpc_credentials_metadata_request *)user_data;
-  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
-  r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
-        GRPC_CREDENTIALS_OK);
-  grpc_credentials_metadata_request_destroy(r);
-}
-
-static void md_only_test_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
-    void *user_data) {
-  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
-
-  if (c->is_async) {
-    grpc_credentials_metadata_request *cb_arg =
-        grpc_credentials_metadata_request_create(creds, cb, user_data);
-    grpc_executor_enqueue(
-        grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true);
-  } else {
-    cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
-  }
-}
-
-static grpc_call_credentials_vtable md_only_test_vtable = {
-    md_only_test_destruct, md_only_test_get_request_metadata};
-
-grpc_call_credentials *grpc_md_only_test_credentials_create(
-    const char *md_key, const char *md_value, int is_async) {
-  grpc_md_only_test_credentials *c =
-      gpr_malloc(sizeof(grpc_md_only_test_credentials));
-  memset(c, 0, sizeof(grpc_md_only_test_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
-  c->base.vtable = &md_only_test_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->md_store = grpc_credentials_md_store_create(1);
-  grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
-  c->is_async = is_async;
-  return &c->base;
-}
-
-/* -- Oauth2 Access Token credentials. -- */
-
-static void access_token_destruct(grpc_call_credentials *creds) {
-  grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
-  grpc_credentials_md_store_unref(c->access_token_md);
-}
-
-static void access_token_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
-    void *user_data) {
-  grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
-  cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
-}
-
-static grpc_call_credentials_vtable access_token_vtable = {
-    access_token_destruct, access_token_get_request_metadata};
-
-grpc_call_credentials *grpc_access_token_credentials_create(
-    const char *access_token, void *reserved) {
-  grpc_access_token_credentials *c =
-      gpr_malloc(sizeof(grpc_access_token_credentials));
-  char *token_md_value;
-  GRPC_API_TRACE(
-      "grpc_access_token_credentials_create(access_token=%s, "
-      "reserved=%p)",
-      2, (access_token, reserved));
-  GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_access_token_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
-  c->base.vtable = &access_token_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->access_token_md = grpc_credentials_md_store_create(1);
-  gpr_asprintf(&token_md_value, "Bearer %s", access_token);
-  grpc_credentials_md_store_add_cstrings(
-      c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
-  gpr_free(token_md_value);
-  return &c->base;
-}
-
-/* -- Fake transport security credentials. -- */
-
-static grpc_security_status fake_transport_security_create_security_connector(
-    grpc_channel_credentials *c, grpc_call_credentials *call_creds,
-    const char *target, const grpc_channel_args *args,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
-  *sc = grpc_fake_channel_security_connector_create(call_creds);
-  return GRPC_SECURITY_OK;
-}
-
-static grpc_security_status
-fake_transport_security_server_create_security_connector(
-    grpc_server_credentials *c, grpc_server_security_connector **sc) {
-  *sc = grpc_fake_server_security_connector_create();
-  return GRPC_SECURITY_OK;
-}
-
-static grpc_channel_credentials_vtable
-    fake_transport_security_credentials_vtable = {
-        NULL, fake_transport_security_create_security_connector};
-
-static grpc_server_credentials_vtable
-    fake_transport_security_server_credentials_vtable = {
-        NULL, fake_transport_security_server_create_security_connector};
-
-grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
-    void) {
-  grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
-  memset(c, 0, sizeof(grpc_channel_credentials));
-  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
-  c->vtable = &fake_transport_security_credentials_vtable;
-  gpr_ref_init(&c->refcount, 1);
-  return c;
-}
-
-grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
-    void) {
-  grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
-  memset(c, 0, sizeof(grpc_server_credentials));
-  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
-  gpr_ref_init(&c->refcount, 1);
-  c->vtable = &fake_transport_security_server_credentials_vtable;
-  return c;
-}
-
-/* -- Composite call credentials. -- */
-
-typedef struct {
-  grpc_composite_call_credentials *composite_creds;
-  size_t creds_index;
-  grpc_credentials_md_store *md_elems;
-  grpc_auth_metadata_context auth_md_context;
-  void *user_data;
-  grpc_pops *pops;
-  grpc_credentials_metadata_cb cb;
-} grpc_composite_call_credentials_metadata_context;
-
-static void composite_call_destruct(grpc_call_credentials *creds) {
-  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->inner.num_creds; i++) {
-    grpc_call_credentials_unref(c->inner.creds_array[i]);
-  }
-  gpr_free(c->inner.creds_array);
-}
-
-static void composite_call_md_context_destroy(
-    grpc_composite_call_credentials_metadata_context *ctx) {
-  grpc_credentials_md_store_unref(ctx->md_elems);
-  gpr_free(ctx);
-}
-
-static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       grpc_credentials_md *md_elems,
-                                       size_t num_md,
-                                       grpc_credentials_status status) {
-  grpc_composite_call_credentials_metadata_context *ctx =
-      (grpc_composite_call_credentials_metadata_context *)user_data;
-  if (status != GRPC_CREDENTIALS_OK) {
-    ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
-    return;
-  }
-
-  /* Copy the metadata in the context. */
-  if (num_md > 0) {
-    size_t i;
-    for (i = 0; i < num_md; i++) {
-      grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
-                                    md_elems[i].value);
-    }
-  }
-
-  /* See if we need to get some more metadata. */
-  if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
-    grpc_call_credentials *inner_creds =
-        ctx->composite_creds->inner.creds_array[ctx->creds_index++];
-    grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pops,
-                                               ctx->auth_md_context,
-                                               composite_call_metadata_cb, ctx);
-    return;
-  }
-
-  /* We're done!. */
-  ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
-          ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
-  composite_call_md_context_destroy(ctx);
-}
-
-static void composite_call_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context auth_md_context, grpc_credentials_metadata_cb cb,
-    void *user_data) {
-  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
-  grpc_composite_call_credentials_metadata_context *ctx;
-
-  ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
-  memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
-  ctx->auth_md_context = auth_md_context;
-  ctx->user_data = user_data;
-  ctx->cb = cb;
-  ctx->composite_creds = c;
-  ctx->pops = pops;
-  ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
-  grpc_call_credentials_get_request_metadata(
-      exec_ctx, c->inner.creds_array[ctx->creds_index++], pops, auth_md_context,
-      composite_call_metadata_cb, ctx);
-}
-
-static grpc_call_credentials_vtable composite_call_credentials_vtable = {
-    composite_call_destruct, composite_call_get_request_metadata};
-
-static grpc_call_credentials_array get_creds_array(
-    grpc_call_credentials **creds_addr) {
-  grpc_call_credentials_array result;
-  grpc_call_credentials *creds = *creds_addr;
-  result.creds_array = creds_addr;
-  result.num_creds = 1;
-  if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
-    result = *grpc_composite_call_credentials_get_credentials(creds);
-  }
-  return result;
-}
-
-grpc_call_credentials *grpc_composite_call_credentials_create(
-    grpc_call_credentials *creds1, grpc_call_credentials *creds2,
-    void *reserved) {
-  size_t i;
-  size_t creds_array_byte_size;
-  grpc_call_credentials_array creds1_array;
-  grpc_call_credentials_array creds2_array;
-  grpc_composite_call_credentials *c;
-  GRPC_API_TRACE(
-      "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
-      "reserved=%p)",
-      3, (creds1, creds2, reserved));
-  GPR_ASSERT(reserved == NULL);
-  GPR_ASSERT(creds1 != NULL);
-  GPR_ASSERT(creds2 != NULL);
-  c = gpr_malloc(sizeof(grpc_composite_call_credentials));
-  memset(c, 0, sizeof(grpc_composite_call_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
-  c->base.vtable = &composite_call_credentials_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  creds1_array = get_creds_array(&creds1);
-  creds2_array = get_creds_array(&creds2);
-  c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
-  creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
-  c->inner.creds_array = gpr_malloc(creds_array_byte_size);
-  memset(c->inner.creds_array, 0, creds_array_byte_size);
-  for (i = 0; i < creds1_array.num_creds; i++) {
-    grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
-    c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
-  }
-  for (i = 0; i < creds2_array.num_creds; i++) {
-    grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
-    c->inner.creds_array[i + creds1_array.num_creds] =
-        grpc_call_credentials_ref(cur_creds);
-  }
-  return &c->base;
-}
-
-const grpc_call_credentials_array *
-grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
-  const grpc_composite_call_credentials *c =
-      (const grpc_composite_call_credentials *)creds;
-  GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
-  return &c->inner;
-}
-
-grpc_call_credentials *grpc_credentials_contains_type(
-    grpc_call_credentials *creds, const char *type,
-    grpc_call_credentials **composite_creds) {
-  size_t i;
-  if (strcmp(creds->type, type) == 0) {
-    if (composite_creds != NULL) *composite_creds = NULL;
-    return creds;
-  } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
-    const grpc_call_credentials_array *inner_creds_array =
-        grpc_composite_call_credentials_get_credentials(creds);
-    for (i = 0; i < inner_creds_array->num_creds; i++) {
-      if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
-        if (composite_creds != NULL) *composite_creds = creds;
-        return inner_creds_array->creds_array[i];
-      }
-    }
-  }
-  return NULL;
-}
-
-/* -- IAM credentials. -- */
-
-static void iam_destruct(grpc_call_credentials *creds) {
-  grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
-  grpc_credentials_md_store_unref(c->iam_md);
-}
-
-static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                     grpc_call_credentials *creds,
-                                     grpc_pops *pops,
-                                     grpc_auth_metadata_context context,
-                                     grpc_credentials_metadata_cb cb,
-                                     void *user_data) {
-  grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
-  cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
-     GRPC_CREDENTIALS_OK);
-}
-
-static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
-                                                  iam_get_request_metadata};
-
-grpc_call_credentials *grpc_google_iam_credentials_create(
-    const char *token, const char *authority_selector, void *reserved) {
-  grpc_google_iam_credentials *c;
-  GRPC_API_TRACE(
-      "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
-      "reserved=%p)",
-      3, (token, authority_selector, reserved));
-  GPR_ASSERT(reserved == NULL);
-  GPR_ASSERT(token != NULL);
-  GPR_ASSERT(authority_selector != NULL);
-  c = gpr_malloc(sizeof(grpc_google_iam_credentials));
-  memset(c, 0, sizeof(grpc_google_iam_credentials));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
-  c->base.vtable = &iam_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->iam_md = grpc_credentials_md_store_create(2);
-  grpc_credentials_md_store_add_cstrings(
-      c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
-  grpc_credentials_md_store_add_cstrings(
-      c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
-  return &c->base;
-}
-
-/* -- Plugin credentials. -- */
-
-typedef struct {
-  void *user_data;
-  grpc_credentials_metadata_cb cb;
-} grpc_metadata_plugin_request;
-
-static void plugin_destruct(grpc_call_credentials *creds) {
-  grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
-  if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
-    c->plugin.destroy(c->plugin.state);
-  }
-}
-
-static void plugin_md_request_metadata_ready(void *request,
-                                             const grpc_metadata *md,
-                                             size_t num_md,
-                                             grpc_status_code status,
-                                             const char *error_details) {
-  /* called from application code */
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
-  if (status != GRPC_STATUS_OK) {
-    if (error_details != NULL) {
-      gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
-              error_details);
-    }
-    r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
-  } else {
-    size_t i;
-    grpc_credentials_md *md_array = NULL;
-    if (num_md > 0) {
-      md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
-      for (i = 0; i < num_md; i++) {
-        md_array[i].key = gpr_slice_from_copied_string(md[i].key);
-        md_array[i].value =
-            gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
-      }
-    }
-    r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
-    if (md_array != NULL) {
-      for (i = 0; i < num_md; i++) {
-        gpr_slice_unref(md_array[i].key);
-        gpr_slice_unref(md_array[i].value);
-      }
-      gpr_free(md_array);
-    }
-  }
-  gpr_free(r);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                        grpc_call_credentials *creds,
-                                        grpc_pops *pops,
-                                        grpc_auth_metadata_context context,
-                                        grpc_credentials_metadata_cb cb,
-                                        void *user_data) {
-  grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
-  if (c->plugin.get_metadata != NULL) {
-    grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
-    memset(request, 0, sizeof(*request));
-    request->user_data = user_data;
-    request->cb = cb;
-    c->plugin.get_metadata(c->plugin.state, context,
-                           plugin_md_request_metadata_ready, request);
-  } else {
-    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
-  }
-}
-
-static grpc_call_credentials_vtable plugin_vtable = {
-    plugin_destruct, plugin_get_request_metadata};
-
-grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
-    grpc_metadata_credentials_plugin plugin, void *reserved) {
-  grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
-  GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
-                 (reserved));
-  GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(*c));
-  c->base.type = plugin.type;
-  c->base.vtable = &plugin_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->plugin = plugin;
-  return &c->base;
-}
-
-/* -- Composite channel credentials. -- */
-
-static void composite_channel_destruct(grpc_channel_credentials *creds) {
-  grpc_composite_channel_credentials *c =
-      (grpc_composite_channel_credentials *)creds;
-  grpc_channel_credentials_unref(c->inner_creds);
-  grpc_call_credentials_unref(c->call_creds);
-}
-
-static grpc_security_status composite_channel_create_security_connector(
-    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
-    const char *target, const grpc_channel_args *args,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
-  grpc_composite_channel_credentials *c =
-      (grpc_composite_channel_credentials *)creds;
-  grpc_security_status status = GRPC_SECURITY_ERROR;
-
-  GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
-             c->inner_creds->vtable != NULL &&
-             c->inner_creds->vtable->create_security_connector != NULL);
-  /* If we are passed a call_creds, create a call composite to pass it
-     downstream. */
-  if (call_creds != NULL) {
-    grpc_call_credentials *composite_call_creds =
-        grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
-    status = c->inner_creds->vtable->create_security_connector(
-        c->inner_creds, composite_call_creds, target, args, sc, new_args);
-    grpc_call_credentials_unref(composite_call_creds);
-  } else {
-    status = c->inner_creds->vtable->create_security_connector(
-        c->inner_creds, c->call_creds, target, args, sc, new_args);
-  }
-  return status;
-}
-
-static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
-    composite_channel_destruct, composite_channel_create_security_connector};
-
-grpc_channel_credentials *grpc_composite_channel_credentials_create(
-    grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
-    void *reserved) {
-  grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
-  GRPC_API_TRACE(
-      "grpc_composite_channel_credentials_create(channel_creds=%p, "
-      "call_creds=%p, reserved=%p)",
-      3, (channel_creds, call_creds, reserved));
-  c->base.type = channel_creds->type;
-  c->base.vtable = &composite_channel_credentials_vtable;
-  gpr_ref_init(&c->base.refcount, 1);
-  c->inner_creds = grpc_channel_credentials_ref(channel_creds);
-  c->call_creds = grpc_call_credentials_ref(call_creds);
-  return &c->base;
-}
diff --git a/src/core/lib/security/credentials.h b/src/core/lib/security/credentials.h
deleted file mode 100644
index 3d37494..0000000
--- a/src/core/lib/security/credentials.h
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_CREDENTIALS_H
-#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_H
-
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
-#include <grpc/support/sync.h>
-#include "src/core/lib/transport/metadata_batch.h"
-
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/http/parser.h"
-#include "src/core/lib/iomgr/pops.h"
-#include "src/core/lib/security/json_token.h"
-#include "src/core/lib/security/security_connector.h"
-
-struct grpc_http_response;
-
-/* --- Constants. --- */
-
-typedef enum {
-  GRPC_CREDENTIALS_OK = 0,
-  GRPC_CREDENTIALS_ERROR
-} grpc_credentials_status;
-
-#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
-
-#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
-#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
-  "FakeTransportSecurity"
-
-#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
-#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
-#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
-#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
-
-#define GRPC_AUTHORIZATION_METADATA_KEY "authorization"
-#define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \
-  "x-goog-iam-authorization-token"
-#define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector"
-
-#define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud"
-#define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \
-  "application_default_credentials.json"
-
-#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
-
-#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
-#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
-  "/computeMetadata/v1/instance/service-accounts/default/token"
-
-#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com"
-#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token"
-
-#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX                         \
-  "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \
-  "assertion="
-
-#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
-  "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
-
-/* --- Google utils --- */
-
-/* It is the caller's responsibility to gpr_free the result if not NULL. */
-char *grpc_get_well_known_google_credentials_file_path(void);
-
-/* Implementation function for the different platforms. */
-char *grpc_get_well_known_google_credentials_file_path_impl(void);
-
-/* Override for testing only. Not thread-safe */
-typedef char *(*grpc_well_known_credentials_path_getter)(void);
-void grpc_override_well_known_credentials_path_getter(
-    grpc_well_known_credentials_path_getter getter);
-
-/* --- grpc_channel_credentials. --- */
-
-typedef struct {
-  void (*destruct)(grpc_channel_credentials *c);
-
-  grpc_security_status (*create_security_connector)(
-      grpc_channel_credentials *c, grpc_call_credentials *call_creds,
-      const char *target, const grpc_channel_args *args,
-      grpc_channel_security_connector **sc, grpc_channel_args **new_args);
-} grpc_channel_credentials_vtable;
-
-struct grpc_channel_credentials {
-  const grpc_channel_credentials_vtable *vtable;
-  const char *type;
-  gpr_refcount refcount;
-};
-
-grpc_channel_credentials *grpc_channel_credentials_ref(
-    grpc_channel_credentials *creds);
-void grpc_channel_credentials_unref(grpc_channel_credentials *creds);
-
-/* Creates a security connector for the channel. May also create new channel
-   args for the channel to be used in place of the passed in const args if
-   returned non NULL. In that case the caller is responsible for destroying
-   new_args after channel creation. */
-grpc_security_status grpc_channel_credentials_create_security_connector(
-    grpc_channel_credentials *creds, const char *target,
-    const grpc_channel_args *args, grpc_channel_security_connector **sc,
-    grpc_channel_args **new_args);
-
-/* --- grpc_credentials_md. --- */
-
-typedef struct {
-  gpr_slice key;
-  gpr_slice value;
-} grpc_credentials_md;
-
-typedef struct {
-  grpc_credentials_md *entries;
-  size_t num_entries;
-  size_t allocated;
-  gpr_refcount refcount;
-} grpc_credentials_md_store;
-
-grpc_credentials_md_store *grpc_credentials_md_store_create(
-    size_t initial_capacity);
-
-/* Will ref key and value. */
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
-                                   gpr_slice key, gpr_slice value);
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
-                                            const char *key, const char *value);
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
-    grpc_credentials_md_store *store);
-void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
-
-/* --- grpc_call_credentials. --- */
-
-typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
-                                             void *user_data,
-                                             grpc_credentials_md *md_elems,
-                                             size_t num_md,
-                                             grpc_credentials_status status);
-
-typedef struct {
-  void (*destruct)(grpc_call_credentials *c);
-  void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
-                               grpc_call_credentials *c, grpc_pops *pops,
-                               grpc_auth_metadata_context context,
-                               grpc_credentials_metadata_cb cb,
-                               void *user_data);
-} grpc_call_credentials_vtable;
-
-struct grpc_call_credentials {
-  const grpc_call_credentials_vtable *vtable;
-  const char *type;
-  gpr_refcount refcount;
-};
-
-grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
-void grpc_call_credentials_unref(grpc_call_credentials *creds);
-void grpc_call_credentials_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
-    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
-    void *user_data);
-
-typedef struct {
-  grpc_call_credentials **creds_array;
-  size_t num_creds;
-} grpc_call_credentials_array;
-
-const grpc_call_credentials_array *
-grpc_composite_call_credentials_get_credentials(
-    grpc_call_credentials *composite_creds);
-
-/* Returns creds if creds is of the specified type or the inner creds of the
-   specified type (if found), if the creds is of type COMPOSITE.
-   If composite_creds is not NULL, *composite_creds will point to creds if of
-   type COMPOSITE in case of success. */
-grpc_call_credentials *grpc_credentials_contains_type(
-    grpc_call_credentials *creds, const char *type,
-    grpc_call_credentials **composite_creds);
-
-/* Exposed for testing only. */
-grpc_credentials_status
-grpc_oauth2_token_fetcher_credentials_parse_server_response(
-    const struct grpc_http_response *response,
-    grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
-
-void grpc_flush_cached_google_default_credentials(void);
-
-/* Metadata-only credentials with the specified key and value where
-   asynchronicity can be simulated for testing. */
-grpc_call_credentials *grpc_md_only_test_credentials_create(
-    const char *md_key, const char *md_value, int is_async);
-
-/* Private constructor for jwt credentials from an already parsed json key.
-   Takes ownership of the key. */
-grpc_call_credentials *
-grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
-    grpc_auth_json_key key, gpr_timespec token_lifetime);
-
-/* Private constructor for refresh token credentials from an already parsed
-   refresh token. Takes ownership of the refresh token. */
-grpc_call_credentials *
-grpc_refresh_token_credentials_create_from_auth_refresh_token(
-    grpc_auth_refresh_token token);
-
-/* --- grpc_server_credentials. --- */
-
-typedef struct {
-  void (*destruct)(grpc_server_credentials *c);
-  grpc_security_status (*create_security_connector)(
-      grpc_server_credentials *c, grpc_server_security_connector **sc);
-} grpc_server_credentials_vtable;
-
-struct grpc_server_credentials {
-  const grpc_server_credentials_vtable *vtable;
-  const char *type;
-  gpr_refcount refcount;
-  grpc_auth_metadata_processor processor;
-};
-
-grpc_security_status grpc_server_credentials_create_security_connector(
-    grpc_server_credentials *creds, grpc_server_security_connector **sc);
-
-grpc_server_credentials *grpc_server_credentials_ref(
-    grpc_server_credentials *creds);
-
-void grpc_server_credentials_unref(grpc_server_credentials *creds);
-
-#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials"
-
-grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c);
-grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
-grpc_server_credentials *grpc_find_server_credentials_in_args(
-    const grpc_channel_args *args);
-
-/* -- Fake transport security credentials. -- */
-
-/* Creates a fake transport security credentials object for testing. */
-grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
-/* Creates a fake server transport security credentials object for testing. */
-grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
-    void);
-
-/* -- Ssl credentials. -- */
-
-typedef struct {
-  grpc_channel_credentials base;
-  grpc_ssl_config config;
-} grpc_ssl_credentials;
-
-typedef struct {
-  grpc_server_credentials base;
-  grpc_ssl_server_config config;
-} grpc_ssl_server_credentials;
-
-/* -- Channel composite credentials. -- */
-
-typedef struct {
-  grpc_channel_credentials base;
-  grpc_channel_credentials *inner_creds;
-  grpc_call_credentials *call_creds;
-} grpc_composite_channel_credentials;
-
-/* -- Jwt credentials -- */
-
-typedef struct {
-  grpc_call_credentials base;
-
-  /* Have a simple cache for now with just 1 entry. We could have a map based on
-     the service_url for a more sophisticated one. */
-  gpr_mu cache_mu;
-  struct {
-    grpc_credentials_md_store *jwt_md;
-    char *service_url;
-    gpr_timespec jwt_expiration;
-  } cached;
-
-  grpc_auth_json_key key;
-  gpr_timespec jwt_lifetime;
-} grpc_service_account_jwt_access_credentials;
-
-/* -- Oauth2TokenFetcher credentials --
-
-   This object is a base for credentials that need to acquire an oauth2 token
-   from an http service. */
-
-typedef struct grpc_credentials_metadata_request
-    grpc_credentials_metadata_request;
-
-typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
-                                       grpc_credentials_metadata_request *req,
-                                       grpc_httpcli_context *http_context,
-                                       grpc_pops *pops,
-                                       grpc_httpcli_response_cb response_cb,
-                                       gpr_timespec deadline);
-
-typedef struct {
-  grpc_call_credentials base;
-  gpr_mu mu;
-  grpc_credentials_md_store *access_token_md;
-  gpr_timespec token_expiration;
-  grpc_httpcli_context httpcli_context;
-  grpc_fetch_oauth2_func fetch_func;
-} grpc_oauth2_token_fetcher_credentials;
-
-/* -- GoogleRefreshToken credentials. -- */
-
-typedef struct {
-  grpc_oauth2_token_fetcher_credentials base;
-  grpc_auth_refresh_token refresh_token;
-} grpc_google_refresh_token_credentials;
-
-/* -- Oauth2 Access Token credentials. -- */
-
-typedef struct {
-  grpc_call_credentials base;
-  grpc_credentials_md_store *access_token_md;
-} grpc_access_token_credentials;
-
-/* --  Metadata-only Test credentials. -- */
-
-typedef struct {
-  grpc_call_credentials base;
-  grpc_credentials_md_store *md_store;
-  int is_async;
-} grpc_md_only_test_credentials;
-
-/* -- GoogleIAM credentials. -- */
-
-typedef struct {
-  grpc_call_credentials base;
-  grpc_credentials_md_store *iam_md;
-} grpc_google_iam_credentials;
-
-/* -- Composite credentials. -- */
-
-typedef struct {
-  grpc_call_credentials base;
-  grpc_call_credentials_array inner;
-} grpc_composite_call_credentials;
-
-/* -- Plugin credentials. -- */
-
-typedef struct {
-  grpc_call_credentials base;
-  grpc_metadata_credentials_plugin plugin;
-  grpc_credentials_md_store *plugin_md;
-} grpc_plugin_credentials;
-
-#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
new file mode 100644
index 0000000..38abd84
--- /dev/null
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -0,0 +1,263 @@
+/*
+ *
+ * Copyright 2015-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/security/credentials/composite/composite_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/iomgr/pops.h"
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+/* -- Composite call credentials. -- */
+
+typedef struct {
+  grpc_composite_call_credentials *composite_creds;
+  size_t creds_index;
+  grpc_credentials_md_store *md_elems;
+  grpc_auth_metadata_context auth_md_context;
+  void *user_data;
+  grpc_pops *pops;
+  grpc_credentials_metadata_cb cb;
+} grpc_composite_call_credentials_metadata_context;
+
+static void composite_call_destruct(grpc_call_credentials *creds) {
+  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
+  size_t i;
+  for (i = 0; i < c->inner.num_creds; i++) {
+    grpc_call_credentials_unref(c->inner.creds_array[i]);
+  }
+  gpr_free(c->inner.creds_array);
+}
+
+static void composite_call_md_context_destroy(
+    grpc_composite_call_credentials_metadata_context *ctx) {
+  grpc_credentials_md_store_unref(ctx->md_elems);
+  gpr_free(ctx);
+}
+
+static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
+                                       grpc_credentials_md *md_elems,
+                                       size_t num_md,
+                                       grpc_credentials_status status) {
+  grpc_composite_call_credentials_metadata_context *ctx =
+      (grpc_composite_call_credentials_metadata_context *)user_data;
+  if (status != GRPC_CREDENTIALS_OK) {
+    ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
+    return;
+  }
+
+  /* Copy the metadata in the context. */
+  if (num_md > 0) {
+    size_t i;
+    for (i = 0; i < num_md; i++) {
+      grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
+                                    md_elems[i].value);
+    }
+  }
+
+  /* See if we need to get some more metadata. */
+  if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+    grpc_call_credentials *inner_creds =
+        ctx->composite_creds->inner.creds_array[ctx->creds_index++];
+    grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pops,
+                                               ctx->auth_md_context,
+                                               composite_call_metadata_cb, ctx);
+    return;
+  }
+
+  /* We're done!. */
+  ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
+          ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
+  composite_call_md_context_destroy(ctx);
+}
+
+static void composite_call_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
+    grpc_auth_metadata_context auth_md_context, grpc_credentials_metadata_cb cb,
+    void *user_data) {
+  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
+  grpc_composite_call_credentials_metadata_context *ctx;
+
+  ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
+  memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
+  ctx->auth_md_context = auth_md_context;
+  ctx->user_data = user_data;
+  ctx->cb = cb;
+  ctx->composite_creds = c;
+  ctx->pops = pops;
+  ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, c->inner.creds_array[ctx->creds_index++], ctx->pops,
+      auth_md_context, composite_call_metadata_cb, ctx);
+}
+
+static grpc_call_credentials_vtable composite_call_credentials_vtable = {
+    composite_call_destruct, composite_call_get_request_metadata};
+
+static grpc_call_credentials_array get_creds_array(
+    grpc_call_credentials **creds_addr) {
+  grpc_call_credentials_array result;
+  grpc_call_credentials *creds = *creds_addr;
+  result.creds_array = creds_addr;
+  result.num_creds = 1;
+  if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
+    result = *grpc_composite_call_credentials_get_credentials(creds);
+  }
+  return result;
+}
+
+grpc_call_credentials *grpc_composite_call_credentials_create(
+    grpc_call_credentials *creds1, grpc_call_credentials *creds2,
+    void *reserved) {
+  size_t i;
+  size_t creds_array_byte_size;
+  grpc_call_credentials_array creds1_array;
+  grpc_call_credentials_array creds2_array;
+  grpc_composite_call_credentials *c;
+  GRPC_API_TRACE(
+      "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
+      "reserved=%p)",
+      3, (creds1, creds2, reserved));
+  GPR_ASSERT(reserved == NULL);
+  GPR_ASSERT(creds1 != NULL);
+  GPR_ASSERT(creds2 != NULL);
+  c = gpr_malloc(sizeof(grpc_composite_call_credentials));
+  memset(c, 0, sizeof(grpc_composite_call_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
+  c->base.vtable = &composite_call_credentials_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  creds1_array = get_creds_array(&creds1);
+  creds2_array = get_creds_array(&creds2);
+  c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
+  creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
+  c->inner.creds_array = gpr_malloc(creds_array_byte_size);
+  memset(c->inner.creds_array, 0, creds_array_byte_size);
+  for (i = 0; i < creds1_array.num_creds; i++) {
+    grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
+    c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
+  }
+  for (i = 0; i < creds2_array.num_creds; i++) {
+    grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
+    c->inner.creds_array[i + creds1_array.num_creds] =
+        grpc_call_credentials_ref(cur_creds);
+  }
+  return &c->base;
+}
+
+const grpc_call_credentials_array *
+grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
+  const grpc_composite_call_credentials *c =
+      (const grpc_composite_call_credentials *)creds;
+  GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
+  return &c->inner;
+}
+
+grpc_call_credentials *grpc_credentials_contains_type(
+    grpc_call_credentials *creds, const char *type,
+    grpc_call_credentials **composite_creds) {
+  size_t i;
+  if (strcmp(creds->type, type) == 0) {
+    if (composite_creds != NULL) *composite_creds = NULL;
+    return creds;
+  } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
+    const grpc_call_credentials_array *inner_creds_array =
+        grpc_composite_call_credentials_get_credentials(creds);
+    for (i = 0; i < inner_creds_array->num_creds; i++) {
+      if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
+        if (composite_creds != NULL) *composite_creds = creds;
+        return inner_creds_array->creds_array[i];
+      }
+    }
+  }
+  return NULL;
+}
+
+/* -- Composite channel credentials. -- */
+
+static void composite_channel_destruct(grpc_channel_credentials *creds) {
+  grpc_composite_channel_credentials *c =
+      (grpc_composite_channel_credentials *)creds;
+  grpc_channel_credentials_unref(c->inner_creds);
+  grpc_call_credentials_unref(c->call_creds);
+}
+
+static grpc_security_status composite_channel_create_security_connector(
+    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  grpc_composite_channel_credentials *c =
+      (grpc_composite_channel_credentials *)creds;
+  grpc_security_status status = GRPC_SECURITY_ERROR;
+
+  GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
+             c->inner_creds->vtable != NULL &&
+             c->inner_creds->vtable->create_security_connector != NULL);
+  /* If we are passed a call_creds, create a call composite to pass it
+     downstream. */
+  if (call_creds != NULL) {
+    grpc_call_credentials *composite_call_creds =
+        grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
+    status = c->inner_creds->vtable->create_security_connector(
+        c->inner_creds, composite_call_creds, target, args, sc, new_args);
+    grpc_call_credentials_unref(composite_call_creds);
+  } else {
+    status = c->inner_creds->vtable->create_security_connector(
+        c->inner_creds, c->call_creds, target, args, sc, new_args);
+  }
+  return status;
+}
+
+static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
+    composite_channel_destruct, composite_channel_create_security_connector};
+
+grpc_channel_credentials *grpc_composite_channel_credentials_create(
+    grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
+    void *reserved) {
+  grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
+  GRPC_API_TRACE(
+      "grpc_composite_channel_credentials_create(channel_creds=%p, "
+      "call_creds=%p, reserved=%p)",
+      3, (channel_creds, call_creds, reserved));
+  c->base.type = channel_creds->type;
+  c->base.vtable = &composite_channel_credentials_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->inner_creds = grpc_channel_credentials_ref(channel_creds);
+  c->call_creds = grpc_call_credentials_ref(call_creds);
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h
new file mode 100644
index 0000000..0d8966f
--- /dev/null
+++ b/src/core/lib/security/credentials/composite/composite_credentials.h
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+typedef struct {
+  grpc_call_credentials **creds_array;
+  size_t num_creds;
+} grpc_call_credentials_array;
+
+const grpc_call_credentials_array *
+grpc_composite_call_credentials_get_credentials(
+    grpc_call_credentials *composite_creds);
+
+/* Returns creds if creds is of the specified type or the inner creds of the
+   specified type (if found), if the creds is of type COMPOSITE.
+   If composite_creds is not NULL, *composite_creds will point to creds if of
+   type COMPOSITE in case of success. */
+grpc_call_credentials *grpc_credentials_contains_type(
+    grpc_call_credentials *creds, const char *type,
+    grpc_call_credentials **composite_creds);
+
+/* -- Channel composite credentials. -- */
+
+typedef struct {
+  grpc_channel_credentials base;
+  grpc_channel_credentials *inner_creds;
+  grpc_call_credentials *call_creds;
+} grpc_composite_channel_credentials;
+
+/* -- Composite credentials. -- */
+
+typedef struct {
+  grpc_call_credentials base;
+  grpc_call_credentials_array inner;
+} grpc_composite_call_credentials;
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H \
+          */
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
new file mode 100644
index 0000000..b33deef
--- /dev/null
+++ b/src/core/lib/security/credentials/credentials.c
@@ -0,0 +1,231 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/credentials.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+/* -- Common. -- */
+
+grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
+    grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
+    void *user_data) {
+  grpc_credentials_metadata_request *r =
+      gpr_malloc(sizeof(grpc_credentials_metadata_request));
+  r->creds = grpc_call_credentials_ref(creds);
+  r->cb = cb;
+  r->user_data = user_data;
+  return r;
+}
+
+void grpc_credentials_metadata_request_destroy(
+    grpc_credentials_metadata_request *r) {
+  grpc_call_credentials_unref(r->creds);
+  gpr_free(r);
+}
+
+grpc_channel_credentials *grpc_channel_credentials_ref(
+    grpc_channel_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
+  if (creds == NULL) return;
+  if (gpr_unref(&creds->refcount)) {
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
+}
+
+void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
+  GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
+  grpc_channel_credentials_unref(creds);
+}
+
+grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_call_credentials_unref(grpc_call_credentials *creds) {
+  if (creds == NULL) return;
+  if (gpr_unref(&creds->refcount)) {
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
+}
+
+void grpc_call_credentials_release(grpc_call_credentials *creds) {
+  GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
+  grpc_call_credentials_unref(creds);
+}
+
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pops *pops, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
+  if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
+    if (cb != NULL) {
+      cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+    }
+    return;
+  }
+  creds->vtable->get_request_metadata(exec_ctx, creds, pops, context, cb,
+                                      user_data);
+}
+
+grpc_security_status grpc_channel_credentials_create_security_connector(
+    grpc_channel_credentials *channel_creds, const char *target,
+    const grpc_channel_args *args, grpc_channel_security_connector **sc,
+    grpc_channel_args **new_args) {
+  *new_args = NULL;
+  if (channel_creds == NULL) {
+    return GRPC_SECURITY_ERROR;
+  }
+  GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
+  return channel_creds->vtable->create_security_connector(
+      channel_creds, NULL, target, args, sc, new_args);
+}
+
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds) {
+  if (creds == NULL) return;
+  if (gpr_unref(&creds->refcount)) {
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+    if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+      creds->processor.destroy(creds->processor.state);
+    }
+    gpr_free(creds);
+  }
+}
+
+void grpc_server_credentials_release(grpc_server_credentials *creds) {
+  GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds));
+  grpc_server_credentials_unref(creds);
+}
+
+grpc_security_status grpc_server_credentials_create_security_connector(
+    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
+  if (creds == NULL || creds->vtable->create_security_connector == NULL) {
+    gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
+    return GRPC_SECURITY_ERROR;
+  }
+  return creds->vtable->create_security_connector(creds, sc);
+}
+
+void grpc_server_credentials_set_auth_metadata_processor(
+    grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
+  GRPC_API_TRACE(
+      "grpc_server_credentials_set_auth_metadata_processor("
+      "creds=%p, "
+      "processor=grpc_auth_metadata_processor { process: %p, state: %p })",
+      3, (creds, (void *)(intptr_t)processor.process, processor.state));
+  if (creds == NULL) return;
+  if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+    creds->processor.destroy(creds->processor.state);
+  }
+  creds->processor = processor;
+}
+
+static void server_credentials_pointer_arg_destroy(void *p) {
+  grpc_server_credentials_unref(p);
+}
+
+static void *server_credentials_pointer_arg_copy(void *p) {
+  return grpc_server_credentials_ref(p);
+}
+
+static int server_credentials_pointer_cmp(void *a, void *b) {
+  return GPR_ICMP(a, b);
+}
+
+static const grpc_arg_pointer_vtable cred_ptr_vtable = {
+    server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy,
+    server_credentials_pointer_cmp};
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
+  grpc_arg arg;
+  memset(&arg, 0, sizeof(grpc_arg));
+  arg.type = GRPC_ARG_POINTER;
+  arg.key = GRPC_SERVER_CREDENTIALS_ARG;
+  arg.value.pointer.p = p;
+  arg.value.pointer.vtable = &cred_ptr_vtable;
+  return arg;
+}
+
+grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
+  if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
+  if (arg->type != GRPC_ARG_POINTER) {
+    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+            GRPC_SERVER_CREDENTIALS_ARG);
+    return NULL;
+  }
+  return arg->value.pointer.p;
+}
+
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+    const grpc_channel_args *args) {
+  size_t i;
+  if (args == NULL) return NULL;
+  for (i = 0; i < args->num_args; i++) {
+    grpc_server_credentials *p =
+        grpc_server_credentials_from_arg(&args->args[i]);
+    if (p != NULL) return p;
+  }
+  return NULL;
+}
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
new file mode 100644
index 0000000..d3531bc
--- /dev/null
+++ b/src/core/lib/security/credentials/credentials.h
@@ -0,0 +1,237 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_CREDENTIALS_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/transport/metadata_batch.h"
+
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/pops.h"
+#include "src/core/lib/security/transport/security_connector.h"
+
+struct grpc_http_response;
+
+/* --- Constants. --- */
+
+typedef enum {
+  GRPC_CREDENTIALS_OK = 0,
+  GRPC_CREDENTIALS_ERROR
+} grpc_credentials_status;
+
+#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
+
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
+  "FakeTransportSecurity"
+
+#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
+#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
+#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
+#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
+
+#define GRPC_AUTHORIZATION_METADATA_KEY "authorization"
+#define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \
+  "x-goog-iam-authorization-token"
+#define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector"
+
+#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
+
+#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
+#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
+  "/computeMetadata/v1/instance/service-accounts/default/token"
+
+#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com"
+#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token"
+
+#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX                         \
+  "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \
+  "assertion="
+
+#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
+  "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
+
+/* --- Google utils --- */
+
+/* It is the caller's responsibility to gpr_free the result if not NULL. */
+char *grpc_get_well_known_google_credentials_file_path(void);
+
+/* Implementation function for the different platforms. */
+char *grpc_get_well_known_google_credentials_file_path_impl(void);
+
+/* Override for testing only. Not thread-safe */
+typedef char *(*grpc_well_known_credentials_path_getter)(void);
+void grpc_override_well_known_credentials_path_getter(
+    grpc_well_known_credentials_path_getter getter);
+
+/* --- grpc_channel_credentials. --- */
+
+typedef struct {
+  void (*destruct)(grpc_channel_credentials *c);
+
+  grpc_security_status (*create_security_connector)(
+      grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+      const char *target, const grpc_channel_args *args,
+      grpc_channel_security_connector **sc, grpc_channel_args **new_args);
+} grpc_channel_credentials_vtable;
+
+struct grpc_channel_credentials {
+  const grpc_channel_credentials_vtable *vtable;
+  const char *type;
+  gpr_refcount refcount;
+};
+
+grpc_channel_credentials *grpc_channel_credentials_ref(
+    grpc_channel_credentials *creds);
+void grpc_channel_credentials_unref(grpc_channel_credentials *creds);
+
+/* Creates a security connector for the channel. May also create new channel
+   args for the channel to be used in place of the passed in const args if
+   returned non NULL. In that case the caller is responsible for destroying
+   new_args after channel creation. */
+grpc_security_status grpc_channel_credentials_create_security_connector(
+    grpc_channel_credentials *creds, const char *target,
+    const grpc_channel_args *args, grpc_channel_security_connector **sc,
+    grpc_channel_args **new_args);
+
+/* --- grpc_credentials_md. --- */
+
+typedef struct {
+  gpr_slice key;
+  gpr_slice value;
+} grpc_credentials_md;
+
+typedef struct {
+  grpc_credentials_md *entries;
+  size_t num_entries;
+  size_t allocated;
+  gpr_refcount refcount;
+} grpc_credentials_md_store;
+
+grpc_credentials_md_store *grpc_credentials_md_store_create(
+    size_t initial_capacity);
+
+/* Will ref key and value. */
+void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
+                                   gpr_slice key, gpr_slice value);
+void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
+                                            const char *key, const char *value);
+grpc_credentials_md_store *grpc_credentials_md_store_ref(
+    grpc_credentials_md_store *store);
+void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
+
+/* --- grpc_call_credentials. --- */
+
+typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
+                                             void *user_data,
+                                             grpc_credentials_md *md_elems,
+                                             size_t num_md,
+                                             grpc_credentials_status status);
+
+typedef struct {
+  void (*destruct)(grpc_call_credentials *c);
+  void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
+                               grpc_call_credentials *c, grpc_pops *pops,
+                               grpc_auth_metadata_context context,
+                               grpc_credentials_metadata_cb cb,
+                               void *user_data);
+} grpc_call_credentials_vtable;
+
+struct grpc_call_credentials {
+  const grpc_call_credentials_vtable *vtable;
+  const char *type;
+  gpr_refcount refcount;
+};
+
+grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
+void grpc_call_credentials_unref(grpc_call_credentials *creds);
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_pops *pops,
+    grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb,
+    void *user_data);
+
+/* Metadata-only credentials with the specified key and value where
+   asynchronicity can be simulated for testing. */
+grpc_call_credentials *grpc_md_only_test_credentials_create(
+    const char *md_key, const char *md_value, int is_async);
+
+/* --- grpc_server_credentials. --- */
+
+typedef struct {
+  void (*destruct)(grpc_server_credentials *c);
+  grpc_security_status (*create_security_connector)(
+      grpc_server_credentials *c, grpc_server_security_connector **sc);
+} grpc_server_credentials_vtable;
+
+struct grpc_server_credentials {
+  const grpc_server_credentials_vtable *vtable;
+  const char *type;
+  gpr_refcount refcount;
+  grpc_auth_metadata_processor processor;
+};
+
+grpc_security_status grpc_server_credentials_create_security_connector(
+    grpc_server_credentials *creds, grpc_server_security_connector **sc);
+
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds);
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds);
+
+#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials"
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c);
+grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+    const grpc_channel_args *args);
+
+/* -- Credentials Metadata Request. -- */
+
+typedef struct {
+  grpc_call_credentials *creds;
+  grpc_credentials_metadata_cb cb;
+  void *user_data;
+} grpc_credentials_metadata_request;
+
+grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
+    grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
+    void *user_data);
+
+void grpc_credentials_metadata_request_destroy(
+    grpc_credentials_metadata_request *r);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
new file mode 100644
index 0000000..6a352aa
--- /dev/null
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -0,0 +1,101 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/credentials.h"
+
+#include <grpc/support/alloc.h>
+
+#include <string.h>
+
+static void store_ensure_capacity(grpc_credentials_md_store *store) {
+  if (store->num_entries == store->allocated) {
+    store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
+    store->entries = gpr_realloc(
+        store->entries, store->allocated * sizeof(grpc_credentials_md));
+  }
+}
+
+grpc_credentials_md_store *grpc_credentials_md_store_create(
+    size_t initial_capacity) {
+  grpc_credentials_md_store *store =
+      gpr_malloc(sizeof(grpc_credentials_md_store));
+  memset(store, 0, sizeof(grpc_credentials_md_store));
+  if (initial_capacity > 0) {
+    store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
+    store->allocated = initial_capacity;
+  }
+  gpr_ref_init(&store->refcount, 1);
+  return store;
+}
+
+void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
+                                   gpr_slice key, gpr_slice value) {
+  if (store == NULL) return;
+  store_ensure_capacity(store);
+  store->entries[store->num_entries].key = gpr_slice_ref(key);
+  store->entries[store->num_entries].value = gpr_slice_ref(value);
+  store->num_entries++;
+}
+
+void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
+                                            const char *key,
+                                            const char *value) {
+  if (store == NULL) return;
+  store_ensure_capacity(store);
+  store->entries[store->num_entries].key = gpr_slice_from_copied_string(key);
+  store->entries[store->num_entries].value =
+      gpr_slice_from_copied_string(value);
+  store->num_entries++;
+}
+
+grpc_credentials_md_store *grpc_credentials_md_store_ref(
+    grpc_credentials_md_store *store) {
+  if (store == NULL) return NULL;
+  gpr_ref(&store->refcount);
+  return store;
+}
+
+void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) {
+  if (store == NULL) return;
+  if (gpr_unref(&store->refcount)) {
+    if (store->entries != NULL) {
+      size_t i;
+      for (i = 0; i < store->num_entries; i++) {
+        gpr_slice_unref(store->entries[i].key);
+        gpr_slice_unref(store->entries[i].value);
+      }
+      gpr_free(store->entries);
+    }
+    gpr_free(store);
+  }
+}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
new file mode 100644
index 0000000..beb0e5e
--- /dev/null
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -0,0 +1,138 @@
+/*
+ *
+ * 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/security/credentials/fake/fake_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/executor.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+/* -- Fake transport security credentials. -- */
+
+static grpc_security_status fake_transport_security_create_security_connector(
+    grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  *sc = grpc_fake_channel_security_connector_create(call_creds);
+  return GRPC_SECURITY_OK;
+}
+
+static grpc_security_status
+fake_transport_security_server_create_security_connector(
+    grpc_server_credentials *c, grpc_server_security_connector **sc) {
+  *sc = grpc_fake_server_security_connector_create();
+  return GRPC_SECURITY_OK;
+}
+
+static grpc_channel_credentials_vtable
+    fake_transport_security_credentials_vtable = {
+        NULL, fake_transport_security_create_security_connector};
+
+static grpc_server_credentials_vtable
+    fake_transport_security_server_credentials_vtable = {
+        NULL, fake_transport_security_server_create_security_connector};
+
+grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
+    void) {
+  grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
+  memset(c, 0, sizeof(grpc_channel_credentials));
+  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  c->vtable = &fake_transport_security_credentials_vtable;
+  gpr_ref_init(&c->refcount, 1);
+  return c;
+}
+
+grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
+    void) {
+  grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
+  memset(c, 0, sizeof(grpc_server_credentials));
+  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  gpr_ref_init(&c->refcount, 1);
+  c->vtable = &fake_transport_security_server_credentials_vtable;
+  return c;
+}
+
+/* -- Metadata-only test credentials. -- */
+
+static void md_only_test_destruct(grpc_call_credentials *creds) {
+  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
+  grpc_credentials_md_store_unref(c->md_store);
+}
+
+static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
+                                          void *user_data, bool success) {
+  grpc_credentials_metadata_request *r =
+      (grpc_credentials_metadata_request *)user_data;
+  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
+  r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
+        GRPC_CREDENTIALS_OK);
+  grpc_credentials_metadata_request_destroy(r);
+}
+
+static void md_only_test_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pops *pops, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
+  grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
+
+  if (c->is_async) {
+    grpc_credentials_metadata_request *cb_arg =
+        grpc_credentials_metadata_request_create(creds, cb, user_data);
+    grpc_executor_enqueue(
+        grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true);
+  } else {
+    cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
+  }
+}
+
+static grpc_call_credentials_vtable md_only_test_vtable = {
+    md_only_test_destruct, md_only_test_get_request_metadata};
+
+grpc_call_credentials *grpc_md_only_test_credentials_create(
+    const char *md_key, const char *md_value, int is_async) {
+  grpc_md_only_test_credentials *c =
+      gpr_malloc(sizeof(grpc_md_only_test_credentials));
+  memset(c, 0, sizeof(grpc_md_only_test_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
+  c->base.vtable = &md_only_test_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->md_store = grpc_credentials_md_store_create(1);
+  grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
+  c->is_async = is_async;
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
new file mode 100644
index 0000000..9cf3808
--- /dev/null
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+/* -- Fake transport security credentials. -- */
+
+/* Creates a fake transport security credentials object for testing. */
+grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
+
+/* Creates a fake server transport security credentials object for testing. */
+grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
+    void);
+
+/* --  Metadata-only Test credentials. -- */
+
+typedef struct {
+  grpc_call_credentials base;
+  grpc_credentials_md_store *md_store;
+  int is_async;
+} grpc_md_only_test_credentials;
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/google_default/credentials_posix.c b/src/core/lib/security/credentials/google_default/credentials_posix.c
new file mode 100644
index 0000000..42c9d7f
--- /dev/null
+++ b/src/core/lib/security/credentials/google_default/credentials_posix.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015, 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 <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_FILE
+
+#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+
+char *grpc_get_well_known_google_credentials_file_path_impl(void) {
+  char *result = NULL;
+  char *home = gpr_getenv("HOME");
+  if (home == NULL) {
+    gpr_log(GPR_ERROR, "Could not get HOME environment variable.");
+    return NULL;
+  }
+  gpr_asprintf(&result, "%s/.config/%s/%s", home,
+               GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY,
+               GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE);
+  gpr_free(home);
+  return result;
+}
+
+#endif /* GPR_POSIX_FILE */
diff --git a/src/core/lib/security/credentials/google_default/credentials_win32.c b/src/core/lib/security/credentials/google_default/credentials_win32.c
new file mode 100644
index 0000000..cd8b480
--- /dev/null
+++ b/src/core/lib/security/credentials/google_default/credentials_win32.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015, 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 <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+
+char *grpc_get_well_known_google_credentials_file_path_impl(void) {
+  char *result = NULL;
+  char *appdata_path = gpr_getenv("APPDATA");
+  if (appdata_path == NULL) {
+    gpr_log(GPR_ERROR, "Could not get APPDATA environment variable.");
+    return NULL;
+  }
+  gpr_asprintf(&result, "%s/%s/%s", appdata_path,
+               GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY,
+               GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE);
+  gpr_free(appdata_path);
+  return result;
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
new file mode 100644
index 0000000..ddea7a9
--- /dev/null
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -0,0 +1,272 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/credentials.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/pops.h"
+#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
+#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/surface/api_trace.h"
+
+/* -- Constants. -- */
+
+#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
+
+/* -- Default credentials. -- */
+
+static grpc_channel_credentials *default_credentials = NULL;
+static int compute_engine_detection_done = 0;
+static gpr_mu g_state_mu;
+static gpr_mu *g_polling_mu;
+static gpr_once g_once = GPR_ONCE_INIT;
+
+static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
+
+typedef struct {
+  grpc_pops pops;
+  int is_done;
+  int success;
+} compute_engine_detector;
+
+static void on_compute_engine_detection_http_response(
+    grpc_exec_ctx *exec_ctx, void *user_data,
+    const grpc_http_response *response) {
+  compute_engine_detector *detector = (compute_engine_detector *)user_data;
+  if (response != NULL && response->status == 200 && response->hdr_count > 0) {
+    /* Internet providers can return a generic response to all requests, so
+       it is necessary to check that metadata header is present also. */
+    size_t i;
+    for (i = 0; i < response->hdr_count; i++) {
+      grpc_http_header *header = &response->hdrs[i];
+      if (strcmp(header->key, "Metadata-Flavor") == 0 &&
+          strcmp(header->value, "Google") == 0) {
+        detector->success = 1;
+        break;
+      }
+    }
+  }
+  gpr_mu_lock(g_polling_mu);
+  detector->is_done = 1;
+  grpc_pollset_kick(grpc_pops_pollset(&detector->pops), NULL);
+  gpr_mu_unlock(g_polling_mu);
+}
+
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) {
+  grpc_pollset_destroy(p);
+}
+
+static int is_stack_running_on_compute_engine(void) {
+  compute_engine_detector detector;
+  grpc_httpcli_request request;
+  grpc_httpcli_context context;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_closure destroy_closure;
+
+  /* The http call is local. If it takes more than one sec, it is for sure not
+     on compute engine. */
+  gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
+
+  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(pollset, &g_polling_mu);
+  detector.pops = grpc_pops_create_from_pollset(pollset);
+  detector.is_done = 0;
+  detector.success = 0;
+
+  memset(&request, 0, sizeof(grpc_httpcli_request));
+  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
+  request.http.path = "/";
+
+  grpc_httpcli_context_init(&context);
+
+  grpc_httpcli_get(
+      &exec_ctx, &context, &detector.pops, &request,
+      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
+      on_compute_engine_detection_http_response, &detector);
+
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  /* Block until we get the response. This is not ideal but this should only be
+     called once for the lifetime of the process by the default credentials. */
+  gpr_mu_lock(g_polling_mu);
+  while (!detector.is_done) {
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, grpc_pops_pollset(&detector.pops), &worker,
+                      gpr_now(GPR_CLOCK_MONOTONIC),
+                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+  }
+  gpr_mu_unlock(g_polling_mu);
+
+  grpc_httpcli_context_destroy(&context);
+  grpc_closure_init(&destroy_closure, destroy_pollset,
+                    grpc_pops_pollset(&detector.pops));
+  grpc_pollset_shutdown(&exec_ctx, grpc_pops_pollset(&detector.pops),
+                        &destroy_closure);
+  grpc_exec_ctx_finish(&exec_ctx);
+  g_polling_mu = NULL;
+
+  gpr_free(grpc_pops_pollset(&detector.pops));
+
+  return detector.success;
+}
+
+/* Takes ownership of creds_path if not NULL. */
+static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
+  grpc_json *json = NULL;
+  grpc_auth_json_key key;
+  grpc_auth_refresh_token token;
+  grpc_call_credentials *result = NULL;
+  gpr_slice creds_data = gpr_empty_slice();
+  int file_ok = 0;
+  if (creds_path == NULL) goto end;
+  creds_data = gpr_load_file(creds_path, 0, &file_ok);
+  if (!file_ok) goto end;
+  json = grpc_json_parse_string_with_len(
+      (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
+  if (json == NULL) goto end;
+
+  /* First, try an auth json key. */
+  key = grpc_auth_json_key_create_from_json(json);
+  if (grpc_auth_json_key_is_valid(&key)) {
+    result =
+        grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
+            key, grpc_max_auth_token_lifetime());
+    goto end;
+  }
+
+  /* Then try a refresh token if the auth json key was invalid. */
+  token = grpc_auth_refresh_token_create_from_json(json);
+  if (grpc_auth_refresh_token_is_valid(&token)) {
+    result =
+        grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
+    goto end;
+  }
+
+end:
+  if (creds_path != NULL) gpr_free(creds_path);
+  gpr_slice_unref(creds_data);
+  if (json != NULL) grpc_json_destroy(json);
+  return result;
+}
+
+grpc_channel_credentials *grpc_google_default_credentials_create(void) {
+  grpc_channel_credentials *result = NULL;
+  grpc_call_credentials *call_creds = NULL;
+
+  GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
+
+  gpr_once_init(&g_once, init_default_credentials);
+
+  gpr_mu_lock(&g_state_mu);
+
+  if (default_credentials != NULL) {
+    result = grpc_channel_credentials_ref(default_credentials);
+    goto end;
+  }
+
+  /* First, try the environment variable. */
+  call_creds = create_default_creds_from_path(
+      gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
+  if (call_creds != NULL) goto end;
+
+  /* Then the well-known file. */
+  call_creds = create_default_creds_from_path(
+      grpc_get_well_known_google_credentials_file_path());
+  if (call_creds != NULL) goto end;
+
+  /* At last try to see if we're on compute engine (do the detection only once
+     since it requires a network test). */
+  if (!compute_engine_detection_done) {
+    int need_compute_engine_creds = is_stack_running_on_compute_engine();
+    compute_engine_detection_done = 1;
+    if (need_compute_engine_creds) {
+      call_creds = grpc_google_compute_engine_credentials_create(NULL);
+    }
+  }
+
+end:
+  if (result == NULL) {
+    if (call_creds != NULL) {
+      /* Blend with default ssl credentials and add a global reference so that
+         it
+         can be cached and re-served. */
+      grpc_channel_credentials *ssl_creds =
+          grpc_ssl_credentials_create(NULL, NULL, NULL);
+      default_credentials = grpc_channel_credentials_ref(
+          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
+                                                    NULL));
+      GPR_ASSERT(default_credentials != NULL);
+      grpc_channel_credentials_unref(ssl_creds);
+      grpc_call_credentials_unref(call_creds);
+      result = default_credentials;
+    } else {
+      gpr_log(GPR_ERROR, "Could not create google default credentials.");
+    }
+  }
+  gpr_mu_unlock(&g_state_mu);
+  return result;
+}
+
+void grpc_flush_cached_google_default_credentials(void) {
+  gpr_once_init(&g_once, init_default_credentials);
+  gpr_mu_lock(&g_state_mu);
+  if (default_credentials != NULL) {
+    grpc_channel_credentials_unref(default_credentials);
+    default_credentials = NULL;
+  }
+  compute_engine_detection_done = 0;
+  gpr_mu_unlock(&g_state_mu);
+}
+
+/* -- Well known credentials path. -- */
+
+static grpc_well_known_credentials_path_getter creds_path_getter = NULL;
+
+char *grpc_get_well_known_google_credentials_file_path(void) {
+  if (creds_path_getter != NULL) return creds_path_getter();
+  return grpc_get_well_known_google_credentials_file_path_impl();
+}
+
+void grpc_override_well_known_credentials_path_getter(
+    grpc_well_known_credentials_path_getter getter) {
+  creds_path_getter = getter;
+}
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.h b/src/core/lib/security/credentials/google_default/google_default_credentials.h
new file mode 100644
index 0000000..fac4377
--- /dev/null
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+#define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud"
+#define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \
+  "application_default_credentials.json"
+
+void grpc_flush_cached_google_default_credentials(void);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H \
+          */
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
new file mode 100644
index 0000000..90779cf
--- /dev/null
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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/security/credentials/iam/iam_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+
+static void iam_destruct(grpc_call_credentials *creds) {
+  grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
+  grpc_credentials_md_store_unref(c->iam_md);
+}
+
+static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_credentials *creds,
+                                     grpc_pops* pops,
+                                     grpc_auth_metadata_context context,
+                                     grpc_credentials_metadata_cb cb,
+                                     void *user_data) {
+  grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
+  cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
+     GRPC_CREDENTIALS_OK);
+}
+
+static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
+                                                  iam_get_request_metadata};
+
+grpc_call_credentials *grpc_google_iam_credentials_create(
+    const char *token, const char *authority_selector, void *reserved) {
+  grpc_google_iam_credentials *c;
+  GRPC_API_TRACE(
+      "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
+      "reserved=%p)",
+      3, (token, authority_selector, reserved));
+  GPR_ASSERT(reserved == NULL);
+  GPR_ASSERT(token != NULL);
+  GPR_ASSERT(authority_selector != NULL);
+  c = gpr_malloc(sizeof(grpc_google_iam_credentials));
+  memset(c, 0, sizeof(grpc_google_iam_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
+  c->base.vtable = &iam_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->iam_md = grpc_credentials_md_store_create(2);
+  grpc_credentials_md_store_add_cstrings(
+      c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
+  grpc_credentials_md_store_add_cstrings(
+      c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h
new file mode 100644
index 0000000..af54faa
--- /dev/null
+++ b/src/core/lib/security/credentials/iam/iam_credentials.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+typedef struct {
+  grpc_call_credentials base;
+  grpc_credentials_md_store *iam_md;
+} grpc_google_iam_credentials;
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/json_token.c b/src/core/lib/security/credentials/jwt/json_token.c
new file mode 100644
index 0000000..354c131
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/json_token.c
@@ -0,0 +1,320 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/jwt/json_token.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/security/util/json_util.h"
+#include "src/core/lib/support/string.h"
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+/* --- Constants. --- */
+
+/* 1 hour max. */
+gpr_timespec grpc_max_auth_token_lifetime() {
+  gpr_timespec out;
+  out.tv_sec = 3600;
+  out.tv_nsec = 0;
+  out.clock_type = GPR_TIMESPAN;
+  return out;
+}
+
+#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
+#define GRPC_JWT_TYPE "JWT"
+
+/* --- Override for testing. --- */
+
+static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL;
+
+/* --- grpc_auth_json_key. --- */
+
+int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) {
+  return (json_key != NULL) &&
+         strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
+}
+
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) {
+  grpc_auth_json_key result;
+  BIO *bio = NULL;
+  const char *prop_value;
+  int success = 0;
+
+  memset(&result, 0, sizeof(grpc_auth_json_key));
+  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (json == NULL) {
+    gpr_log(GPR_ERROR, "Invalid json.");
+    goto end;
+  }
+
+  prop_value = grpc_json_get_string_property(json, "type");
+  if (prop_value == NULL ||
+      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) {
+    goto end;
+  }
+  result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT;
+
+  if (!grpc_copy_json_string_property(json, "private_key_id",
+                                      &result.private_key_id) ||
+      !grpc_copy_json_string_property(json, "client_id", &result.client_id) ||
+      !grpc_copy_json_string_property(json, "client_email",
+                                      &result.client_email)) {
+    goto end;
+  }
+
+  prop_value = grpc_json_get_string_property(json, "private_key");
+  if (prop_value == NULL) {
+    goto end;
+  }
+  bio = BIO_new(BIO_s_mem());
+  success = BIO_puts(bio, prop_value);
+  if ((success < 0) || ((size_t)success != strlen(prop_value))) {
+    gpr_log(GPR_ERROR, "Could not write into openssl BIO.");
+    goto end;
+  }
+  result.private_key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, "");
+  if (result.private_key == NULL) {
+    gpr_log(GPR_ERROR, "Could not deserialize private key.");
+    goto end;
+  }
+  success = 1;
+
+end:
+  if (bio != NULL) BIO_free(bio);
+  if (!success) grpc_auth_json_key_destruct(&result);
+  return result;
+}
+
+grpc_auth_json_key grpc_auth_json_key_create_from_string(
+    const char *json_string) {
+  char *scratchpad = gpr_strdup(json_string);
+  grpc_json *json = grpc_json_parse_string(scratchpad);
+  grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json);
+  if (json != NULL) grpc_json_destroy(json);
+  gpr_free(scratchpad);
+  return result;
+}
+
+void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) {
+  if (json_key == NULL) return;
+  json_key->type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (json_key->client_id != NULL) {
+    gpr_free(json_key->client_id);
+    json_key->client_id = NULL;
+  }
+  if (json_key->private_key_id != NULL) {
+    gpr_free(json_key->private_key_id);
+    json_key->private_key_id = NULL;
+  }
+  if (json_key->client_email != NULL) {
+    gpr_free(json_key->client_email);
+    json_key->client_email = NULL;
+  }
+  if (json_key->private_key != NULL) {
+    RSA_free(json_key->private_key);
+    json_key->private_key = NULL;
+  }
+}
+
+/* --- jwt encoding and signature. --- */
+
+static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
+                               const char *key, const char *value,
+                               grpc_json_type type) {
+  grpc_json *child = grpc_json_create(type);
+  if (brother) brother->next = child;
+  if (!parent->child) parent->child = child;
+  child->parent = parent;
+  child->value = value;
+  child->key = key;
+  return child;
+}
+
+static char *encoded_jwt_header(const char *key_id, const char *algorithm) {
+  grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
+  grpc_json *child = NULL;
+  char *json_str = NULL;
+  char *result = NULL;
+
+  child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING);
+  child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
+  create_child(child, json, "kid", key_id, GRPC_JSON_STRING);
+
+  json_str = grpc_json_dump_to_string(json, 0);
+  result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
+  gpr_free(json_str);
+  grpc_json_destroy(json);
+  return result;
+}
+
+static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
+                               const char *audience,
+                               gpr_timespec token_lifetime, const char *scope) {
+  grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
+  grpc_json *child = NULL;
+  char *json_str = NULL;
+  char *result = NULL;
+  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+  gpr_timespec expiration = gpr_time_add(now, token_lifetime);
+  char now_str[GPR_LTOA_MIN_BUFSIZE];
+  char expiration_str[GPR_LTOA_MIN_BUFSIZE];
+  if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) {
+    gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value.");
+    expiration = gpr_time_add(now, grpc_max_auth_token_lifetime());
+  }
+  int64_ttoa(now.tv_sec, now_str);
+  int64_ttoa(expiration.tv_sec, expiration_str);
+
+  child =
+      create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING);
+  if (scope != NULL) {
+    child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
+  } else {
+    /* Unscoped JWTs need a sub field. */
+    child = create_child(child, json, "sub", json_key->client_email,
+                         GRPC_JSON_STRING);
+  }
+
+  child = create_child(child, json, "aud", audience, GRPC_JSON_STRING);
+  child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER);
+  create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER);
+
+  json_str = grpc_json_dump_to_string(json, 0);
+  result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
+  gpr_free(json_str);
+  grpc_json_destroy(json);
+  return result;
+}
+
+static char *dot_concat_and_free_strings(char *str1, char *str2) {
+  size_t str1_len = strlen(str1);
+  size_t str2_len = strlen(str2);
+  size_t result_len = str1_len + 1 /* dot */ + str2_len;
+  char *result = gpr_malloc(result_len + 1 /* NULL terminated */);
+  char *current = result;
+  memcpy(current, str1, str1_len);
+  current += str1_len;
+  *(current++) = '.';
+  memcpy(current, str2, str2_len);
+  current += str2_len;
+  GPR_ASSERT(current >= result);
+  GPR_ASSERT((uintptr_t)(current - result) == result_len);
+  *current = '\0';
+  gpr_free(str1);
+  gpr_free(str2);
+  return result;
+}
+
+const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) {
+  if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) {
+    return EVP_sha256();
+  } else {
+    gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm);
+    return NULL;
+  }
+}
+
+char *compute_and_encode_signature(const grpc_auth_json_key *json_key,
+                                   const char *signature_algorithm,
+                                   const char *to_sign) {
+  const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm);
+  EVP_MD_CTX *md_ctx = NULL;
+  EVP_PKEY *key = EVP_PKEY_new();
+  size_t sig_len = 0;
+  unsigned char *sig = NULL;
+  char *result = NULL;
+  if (md == NULL) return NULL;
+  md_ctx = EVP_MD_CTX_create();
+  if (md_ctx == NULL) {
+    gpr_log(GPR_ERROR, "Could not create MD_CTX");
+    goto end;
+  }
+  EVP_PKEY_set1_RSA(key, json_key->private_key);
+  if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) {
+    gpr_log(GPR_ERROR, "DigestInit failed.");
+    goto end;
+  }
+  if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) {
+    gpr_log(GPR_ERROR, "DigestUpdate failed.");
+    goto end;
+  }
+  if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
+    gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed.");
+    goto end;
+  }
+  sig = gpr_malloc(sig_len);
+  if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
+    gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
+    goto end;
+  }
+  result = grpc_base64_encode(sig, sig_len, 1, 0);
+
+end:
+  if (key != NULL) EVP_PKEY_free(key);
+  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
+  if (sig != NULL) gpr_free(sig);
+  return result;
+}
+
+char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
+                               const char *audience,
+                               gpr_timespec token_lifetime, const char *scope) {
+  if (g_jwt_encode_and_sign_override != NULL) {
+    return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime,
+                                          scope);
+  } else {
+    const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM;
+    char *to_sign = dot_concat_and_free_strings(
+        encoded_jwt_header(json_key->private_key_id, sig_algo),
+        encoded_jwt_claim(json_key, audience, token_lifetime, scope));
+    char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign);
+    if (sig == NULL) {
+      gpr_free(to_sign);
+      return NULL;
+    }
+    return dot_concat_and_free_strings(to_sign, sig);
+  }
+}
+
+void grpc_jwt_encode_and_sign_set_override(
+    grpc_jwt_encode_and_sign_override func) {
+  g_jwt_encode_and_sign_override = func;
+}
diff --git a/src/core/lib/security/credentials/jwt/json_token.h b/src/core/lib/security/credentials/jwt/json_token.h
new file mode 100644
index 0000000..07fc5bf
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/json_token.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H
+
+#include <grpc/support/slice.h>
+#include <openssl/rsa.h>
+
+#include "src/core/lib/json/json.h"
+
+/* --- Constants. --- */
+
+#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
+
+/* --- auth_json_key parsing. --- */
+
+typedef struct {
+  const char *type;
+  char *private_key_id;
+  char *client_id;
+  char *client_email;
+  RSA *private_key;
+} grpc_auth_json_key;
+
+/* Returns 1 if the object is valid, 0 otherwise. */
+int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key);
+
+/* Creates a json_key object from string. Returns an invalid object if a parsing
+   error has been encountered. */
+grpc_auth_json_key grpc_auth_json_key_create_from_string(
+    const char *json_string);
+
+/* Creates a json_key object from parsed json. Returns an invalid object if a
+   parsing error has been encountered. */
+grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
+
+/* Destructs the object. */
+void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
+
+/* --- json token encoding and signing. --- */
+
+/* Caller is responsible for calling gpr_free on the returned value. May return
+   NULL on invalid input. The scope parameter may be NULL. */
+char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
+                               const char *audience,
+                               gpr_timespec token_lifetime, const char *scope);
+
+/* Override encode_and_sign function for testing. */
+typedef char *(*grpc_jwt_encode_and_sign_override)(
+    const grpc_auth_json_key *json_key, const char *audience,
+    gpr_timespec token_lifetime, const char *scope);
+
+/* Set a custom encode_and_sign override for testing. */
+void grpc_jwt_encode_and_sign_set_override(
+    grpc_jwt_encode_and_sign_override func);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
new file mode 100644
index 0000000..590f29b
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -0,0 +1,160 @@
+/*
+ *
+ * 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/security/credentials/jwt/jwt_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+
+static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
+  if (c->cached.jwt_md != NULL) {
+    grpc_credentials_md_store_unref(c->cached.jwt_md);
+    c->cached.jwt_md = NULL;
+  }
+  if (c->cached.service_url != NULL) {
+    gpr_free(c->cached.service_url);
+    c->cached.service_url = NULL;
+  }
+  c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
+}
+
+static void jwt_destruct(grpc_call_credentials *creds) {
+  grpc_service_account_jwt_access_credentials *c =
+      (grpc_service_account_jwt_access_credentials *)creds;
+  grpc_auth_json_key_destruct(&c->key);
+  jwt_reset_cache(c);
+  gpr_mu_destroy(&c->cache_mu);
+}
+
+static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_credentials *creds,
+                                     grpc_pops* pops,
+                                     grpc_auth_metadata_context context,
+                                     grpc_credentials_metadata_cb cb,
+                                     void *user_data) {
+  grpc_service_account_jwt_access_credentials *c =
+      (grpc_service_account_jwt_access_credentials *)creds;
+  gpr_timespec refresh_threshold = gpr_time_from_seconds(
+      GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
+
+  /* See if we can return a cached jwt. */
+  grpc_credentials_md_store *jwt_md = NULL;
+  {
+    gpr_mu_lock(&c->cache_mu);
+    if (c->cached.service_url != NULL &&
+        strcmp(c->cached.service_url, context.service_url) == 0 &&
+        c->cached.jwt_md != NULL &&
+        (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
+                                   gpr_now(GPR_CLOCK_REALTIME)),
+                      refresh_threshold) > 0)) {
+      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+    }
+    gpr_mu_unlock(&c->cache_mu);
+  }
+
+  if (jwt_md == NULL) {
+    char *jwt = NULL;
+    /* Generate a new jwt. */
+    gpr_mu_lock(&c->cache_mu);
+    jwt_reset_cache(c);
+    jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
+                                   c->jwt_lifetime, NULL);
+    if (jwt != NULL) {
+      char *md_value;
+      gpr_asprintf(&md_value, "Bearer %s", jwt);
+      gpr_free(jwt);
+      c->cached.jwt_expiration =
+          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
+      c->cached.service_url = gpr_strdup(context.service_url);
+      c->cached.jwt_md = grpc_credentials_md_store_create(1);
+      grpc_credentials_md_store_add_cstrings(
+          c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
+      gpr_free(md_value);
+      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+    }
+    gpr_mu_unlock(&c->cache_mu);
+  }
+
+  if (jwt_md != NULL) {
+    cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
+       GRPC_CREDENTIALS_OK);
+    grpc_credentials_md_store_unref(jwt_md);
+  } else {
+    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+  }
+}
+
+static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
+                                                  jwt_get_request_metadata};
+
+grpc_call_credentials *
+grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
+    grpc_auth_json_key key, gpr_timespec token_lifetime) {
+  grpc_service_account_jwt_access_credentials *c;
+  if (!grpc_auth_json_key_is_valid(&key)) {
+    gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
+    return NULL;
+  }
+  c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
+  memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->base.vtable = &jwt_vtable;
+  c->key = key;
+  c->jwt_lifetime = token_lifetime;
+  gpr_mu_init(&c->cache_mu);
+  jwt_reset_cache(c);
+  return &c->base;
+}
+
+grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
+    const char *json_key, gpr_timespec token_lifetime, void *reserved) {
+  GRPC_API_TRACE(
+      "grpc_service_account_jwt_access_credentials_create("
+      "json_key=%s, "
+      "token_lifetime="
+      "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
+      "reserved=%p)",
+      5,
+      (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec,
+       (int)token_lifetime.clock_type, reserved));
+  GPR_ASSERT(reserved == NULL);
+  return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
+      grpc_auth_json_key_create_from_string(json_key), token_lifetime);
+}
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
new file mode 100644
index 0000000..d572606
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/credentials/jwt/json_token.h"
+
+typedef struct {
+  grpc_call_credentials base;
+
+  // Have a simple cache for now with just 1 entry. We could have a map based on
+  // the service_url for a more sophisticated one.
+  gpr_mu cache_mu;
+  struct {
+    grpc_credentials_md_store *jwt_md;
+    char *service_url;
+    gpr_timespec jwt_expiration;
+  } cached;
+
+  grpc_auth_json_key key;
+  gpr_timespec jwt_lifetime;
+} grpc_service_account_jwt_access_credentials;
+
+// Private constructor for jwt credentials from an already parsed json key.
+// Takes ownership of the key.
+grpc_call_credentials *
+grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
+    grpc_auth_json_key key, gpr_timespec token_lifetime);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
new file mode 100644
index 0000000..a3e0c2d
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -0,0 +1,846 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/jwt/jwt_verifier.h"
+
+#include <limits.h>
+#include <string.h>
+
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/iomgr/pops.h"
+#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/tsi/ssl_types.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <openssl/pem.h>
+
+/* --- Utils. --- */
+
+const char *grpc_jwt_verifier_status_to_string(
+    grpc_jwt_verifier_status status) {
+  switch (status) {
+    case GRPC_JWT_VERIFIER_OK:
+      return "OK";
+    case GRPC_JWT_VERIFIER_BAD_SIGNATURE:
+      return "BAD_SIGNATURE";
+    case GRPC_JWT_VERIFIER_BAD_FORMAT:
+      return "BAD_FORMAT";
+    case GRPC_JWT_VERIFIER_BAD_AUDIENCE:
+      return "BAD_AUDIENCE";
+    case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR:
+      return "KEY_RETRIEVAL_ERROR";
+    case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE:
+      return "TIME_CONSTRAINT_FAILURE";
+    case GRPC_JWT_VERIFIER_GENERIC_ERROR:
+      return "GENERIC_ERROR";
+    default:
+      return "UNKNOWN";
+  }
+}
+
+static const EVP_MD *evp_md_from_alg(const char *alg) {
+  if (strcmp(alg, "RS256") == 0) {
+    return EVP_sha256();
+  } else if (strcmp(alg, "RS384") == 0) {
+    return EVP_sha384();
+  } else if (strcmp(alg, "RS512") == 0) {
+    return EVP_sha512();
+  } else {
+    return NULL;
+  }
+}
+
+static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
+                                           gpr_slice *buffer) {
+  grpc_json *json;
+
+  *buffer = grpc_base64_decode_with_len(str, len, 1);
+  if (GPR_SLICE_IS_EMPTY(*buffer)) {
+    gpr_log(GPR_ERROR, "Invalid base64.");
+    return NULL;
+  }
+  json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer),
+                                         GPR_SLICE_LENGTH(*buffer));
+  if (json == NULL) {
+    gpr_slice_unref(*buffer);
+    gpr_log(GPR_ERROR, "JSON parsing error.");
+  }
+  return json;
+}
+
+static const char *validate_string_field(const grpc_json *json,
+                                         const char *key) {
+  if (json->type != GRPC_JSON_STRING) {
+    gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
+    return NULL;
+  }
+  return json->value;
+}
+
+static gpr_timespec validate_time_field(const grpc_json *json,
+                                        const char *key) {
+  gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME);
+  if (json->type != GRPC_JSON_NUMBER) {
+    gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
+    return result;
+  }
+  result.tv_sec = strtol(json->value, NULL, 10);
+  return result;
+}
+
+/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
+
+typedef struct {
+  const char *alg;
+  const char *kid;
+  const char *typ;
+  /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
+  gpr_slice buffer;
+} jose_header;
+
+static void jose_header_destroy(jose_header *h) {
+  gpr_slice_unref(h->buffer);
+  gpr_free(h);
+}
+
+/* Takes ownership of json and buffer. */
+static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) {
+  grpc_json *cur;
+  jose_header *h = gpr_malloc(sizeof(jose_header));
+  memset(h, 0, sizeof(jose_header));
+  h->buffer = buffer;
+  for (cur = json->child; cur != NULL; cur = cur->next) {
+    if (strcmp(cur->key, "alg") == 0) {
+      /* We only support RSA-1.5 signatures for now.
+         Beware of this if we add HMAC support:
+         https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
+       */
+      if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) ||
+          evp_md_from_alg(cur->value) == NULL) {
+        gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value);
+        goto error;
+      }
+      h->alg = cur->value;
+    } else if (strcmp(cur->key, "typ") == 0) {
+      h->typ = validate_string_field(cur, "typ");
+      if (h->typ == NULL) goto error;
+    } else if (strcmp(cur->key, "kid") == 0) {
+      h->kid = validate_string_field(cur, "kid");
+      if (h->kid == NULL) goto error;
+    }
+  }
+  if (h->alg == NULL) {
+    gpr_log(GPR_ERROR, "Missing alg field.");
+    goto error;
+  }
+  grpc_json_destroy(json);
+  h->buffer = buffer;
+  return h;
+
+error:
+  grpc_json_destroy(json);
+  jose_header_destroy(h);
+  return NULL;
+}
+
+/* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */
+
+struct grpc_jwt_claims {
+  /* Well known properties already parsed. */
+  const char *sub;
+  const char *iss;
+  const char *aud;
+  const char *jti;
+  gpr_timespec iat;
+  gpr_timespec exp;
+  gpr_timespec nbf;
+
+  grpc_json *json;
+  gpr_slice buffer;
+};
+
+void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
+  grpc_json_destroy(claims->json);
+  gpr_slice_unref(claims->buffer);
+  gpr_free(claims);
+}
+
+const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return NULL;
+  return claims->json;
+}
+
+const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return NULL;
+  return claims->sub;
+}
+
+const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return NULL;
+  return claims->iss;
+}
+
+const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return NULL;
+  return claims->jti;
+}
+
+const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return NULL;
+  return claims->aud;
+}
+
+gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
+  return claims->iat;
+}
+
+gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME);
+  return claims->exp;
+}
+
+gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
+  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
+  return claims->nbf;
+}
+
+/* Takes ownership of json and buffer even in case of failure. */
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) {
+  grpc_json *cur;
+  grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims));
+  memset(claims, 0, sizeof(grpc_jwt_claims));
+  claims->json = json;
+  claims->buffer = buffer;
+  claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME);
+  claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME);
+  claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME);
+
+  /* Per the spec, all fields are optional. */
+  for (cur = json->child; cur != NULL; cur = cur->next) {
+    if (strcmp(cur->key, "sub") == 0) {
+      claims->sub = validate_string_field(cur, "sub");
+      if (claims->sub == NULL) goto error;
+    } else if (strcmp(cur->key, "iss") == 0) {
+      claims->iss = validate_string_field(cur, "iss");
+      if (claims->iss == NULL) goto error;
+    } else if (strcmp(cur->key, "aud") == 0) {
+      claims->aud = validate_string_field(cur, "aud");
+      if (claims->aud == NULL) goto error;
+    } else if (strcmp(cur->key, "jti") == 0) {
+      claims->jti = validate_string_field(cur, "jti");
+      if (claims->jti == NULL) goto error;
+    } else if (strcmp(cur->key, "iat") == 0) {
+      claims->iat = validate_time_field(cur, "iat");
+      if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
+    } else if (strcmp(cur->key, "exp") == 0) {
+      claims->exp = validate_time_field(cur, "exp");
+      if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
+    } else if (strcmp(cur->key, "nbf") == 0) {
+      claims->nbf = validate_time_field(cur, "nbf");
+      if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
+    }
+  }
+  return claims;
+
+error:
+  grpc_jwt_claims_destroy(claims);
+  return NULL;
+}
+
+grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
+                                               const char *audience) {
+  gpr_timespec skewed_now;
+  int audience_ok;
+
+  GPR_ASSERT(claims != NULL);
+
+  skewed_now =
+      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
+  if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
+    gpr_log(GPR_ERROR, "JWT is not valid yet.");
+    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
+  }
+  skewed_now =
+      gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
+  if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
+    gpr_log(GPR_ERROR, "JWT is expired.");
+    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
+  }
+
+  if (audience == NULL) {
+    audience_ok = claims->aud == NULL;
+  } else {
+    audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0;
+  }
+  if (!audience_ok) {
+    gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.",
+            audience == NULL ? "NULL" : audience,
+            claims->aud == NULL ? "NULL" : claims->aud);
+    return GRPC_JWT_VERIFIER_BAD_AUDIENCE;
+  }
+  return GRPC_JWT_VERIFIER_OK;
+}
+
+/* --- verifier_cb_ctx object. --- */
+
+typedef struct {
+  grpc_jwt_verifier *verifier;
+  grpc_pops pops;
+  jose_header *header;
+  grpc_jwt_claims *claims;
+  char *audience;
+  gpr_slice signature;
+  gpr_slice signed_data;
+  void *user_data;
+  grpc_jwt_verification_done_cb user_cb;
+} verifier_cb_ctx;
+
+/* Takes ownership of the header, claims and signature. */
+static verifier_cb_ctx *verifier_cb_ctx_create(
+    grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header,
+    grpc_jwt_claims *claims, const char *audience, gpr_slice signature,
+    const char *signed_jwt, size_t signed_jwt_len, void *user_data,
+    grpc_jwt_verification_done_cb cb) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
+  memset(ctx, 0, sizeof(verifier_cb_ctx));
+  ctx->verifier = verifier;
+  ctx->pops = grpc_pops_create_from_pollset(pollset);
+  ctx->header = header;
+  ctx->audience = gpr_strdup(audience);
+  ctx->claims = claims;
+  ctx->signature = signature;
+  ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len);
+  ctx->user_data = user_data;
+  ctx->user_cb = cb;
+  grpc_exec_ctx_finish(&exec_ctx);
+  return ctx;
+}
+
+void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
+  if (ctx->audience != NULL) gpr_free(ctx->audience);
+  if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims);
+  gpr_slice_unref(ctx->signature);
+  gpr_slice_unref(ctx->signed_data);
+  jose_header_destroy(ctx->header);
+  /* TODO: see what to do with claims... */
+  gpr_free(ctx);
+}
+
+/* --- grpc_jwt_verifier object. --- */
+
+/* Clock skew defaults to one minute. */
+gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
+
+/* Max delay defaults to one minute. */
+gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN};
+
+typedef struct {
+  char *email_domain;
+  char *key_url_prefix;
+} email_key_mapping;
+
+struct grpc_jwt_verifier {
+  email_key_mapping *mappings;
+  size_t num_mappings; /* Should be very few, linear search ok. */
+  size_t allocated_mappings;
+  grpc_httpcli_context http_ctx;
+};
+
+static grpc_json *json_from_http(const grpc_httpcli_response *response) {
+  grpc_json *json = NULL;
+
+  if (response == NULL) {
+    gpr_log(GPR_ERROR, "HTTP response is NULL.");
+    return NULL;
+  }
+  if (response->status != 200) {
+    gpr_log(GPR_ERROR, "Call to http server failed with error %d.",
+            response->status);
+    return NULL;
+  }
+
+  json = grpc_json_parse_string_with_len(response->body, response->body_length);
+  if (json == NULL) {
+    gpr_log(GPR_ERROR, "Invalid JSON found in response.");
+  }
+  return json;
+}
+
+static const grpc_json *find_property_by_name(const grpc_json *json,
+                                              const char *name) {
+  const grpc_json *cur;
+  for (cur = json->child; cur != NULL; cur = cur->next) {
+    if (strcmp(cur->key, name) == 0) return cur;
+  }
+  return NULL;
+}
+
+static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
+  X509 *x509 = NULL;
+  EVP_PKEY *result = NULL;
+  BIO *bio = BIO_new(BIO_s_mem());
+  size_t len = strlen(x509_str);
+  GPR_ASSERT(len < INT_MAX);
+  BIO_write(bio, x509_str, (int)len);
+  x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+  if (x509 == NULL) {
+    gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
+    goto end;
+  }
+  result = X509_get_pubkey(x509);
+  if (result == NULL) {
+    gpr_log(GPR_ERROR, "Cannot find public key in X509 cert.");
+  }
+
+end:
+  BIO_free(bio);
+  if (x509 != NULL) X509_free(x509);
+  return result;
+}
+
+static BIGNUM *bignum_from_base64(const char *b64) {
+  BIGNUM *result = NULL;
+  gpr_slice bin;
+
+  if (b64 == NULL) return NULL;
+  bin = grpc_base64_decode(b64, 1);
+  if (GPR_SLICE_IS_EMPTY(bin)) {
+    gpr_log(GPR_ERROR, "Invalid base64 for big num.");
+    return NULL;
+  }
+  result = BN_bin2bn(GPR_SLICE_START_PTR(bin),
+                     TSI_SIZE_AS_SIZE(GPR_SLICE_LENGTH(bin)), NULL);
+  gpr_slice_unref(bin);
+  return result;
+}
+
+static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
+  const grpc_json *key_prop;
+  RSA *rsa = NULL;
+  EVP_PKEY *result = NULL;
+
+  GPR_ASSERT(kty != NULL && json != NULL);
+  if (strcmp(kty, "RSA") != 0) {
+    gpr_log(GPR_ERROR, "Unsupported key type %s.", kty);
+    goto end;
+  }
+  rsa = RSA_new();
+  if (rsa == NULL) {
+    gpr_log(GPR_ERROR, "Could not create rsa key.");
+    goto end;
+  }
+  for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
+    if (strcmp(key_prop->key, "n") == 0) {
+      rsa->n = bignum_from_base64(validate_string_field(key_prop, "n"));
+      if (rsa->n == NULL) goto end;
+    } else if (strcmp(key_prop->key, "e") == 0) {
+      rsa->e = bignum_from_base64(validate_string_field(key_prop, "e"));
+      if (rsa->e == NULL) goto end;
+    }
+  }
+  if (rsa->e == NULL || rsa->n == NULL) {
+    gpr_log(GPR_ERROR, "Missing RSA public key field.");
+    goto end;
+  }
+  result = EVP_PKEY_new();
+  EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
+
+end:
+  if (rsa != NULL) RSA_free(rsa);
+  return result;
+}
+
+static EVP_PKEY *find_verification_key(const grpc_json *json,
+                                       const char *header_alg,
+                                       const char *header_kid) {
+  const grpc_json *jkey;
+  const grpc_json *jwk_keys;
+  /* Try to parse the json as a JWK set:
+     https://tools.ietf.org/html/rfc7517#section-5. */
+  jwk_keys = find_property_by_name(json, "keys");
+  if (jwk_keys == NULL) {
+    /* Use the google proprietary format which is:
+       { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
+    const grpc_json *cur = find_property_by_name(json, header_kid);
+    if (cur == NULL) return NULL;
+    return extract_pkey_from_x509(cur->value);
+  }
+
+  if (jwk_keys->type != GRPC_JSON_ARRAY) {
+    gpr_log(GPR_ERROR,
+            "Unexpected value type of keys property in jwks key set.");
+    return NULL;
+  }
+  /* Key format is specified in:
+     https://tools.ietf.org/html/rfc7518#section-6. */
+  for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) {
+    grpc_json *key_prop;
+    const char *alg = NULL;
+    const char *kid = NULL;
+    const char *kty = NULL;
+
+    if (jkey->type != GRPC_JSON_OBJECT) continue;
+    for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) {
+      if (strcmp(key_prop->key, "alg") == 0 &&
+          key_prop->type == GRPC_JSON_STRING) {
+        alg = key_prop->value;
+      } else if (strcmp(key_prop->key, "kid") == 0 &&
+                 key_prop->type == GRPC_JSON_STRING) {
+        kid = key_prop->value;
+      } else if (strcmp(key_prop->key, "kty") == 0 &&
+                 key_prop->type == GRPC_JSON_STRING) {
+        kty = key_prop->value;
+      }
+    }
+    if (alg != NULL && kid != NULL && kty != NULL &&
+        strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
+      return pkey_from_jwk(jkey, kty);
+    }
+  }
+  gpr_log(GPR_ERROR,
+          "Could not find matching key in key set for kid=%s and alg=%s",
+          header_kid, header_alg);
+  return NULL;
+}
+
+static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
+                                gpr_slice signature, gpr_slice signed_data) {
+  EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
+  const EVP_MD *md = evp_md_from_alg(alg);
+  int result = 0;
+
+  GPR_ASSERT(md != NULL); /* Checked before. */
+  if (md_ctx == NULL) {
+    gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX.");
+    goto end;
+  }
+  if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) {
+    gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed.");
+    goto end;
+  }
+  if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data),
+                             GPR_SLICE_LENGTH(signed_data)) != 1) {
+    gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
+    goto end;
+  }
+  if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature),
+                            GPR_SLICE_LENGTH(signature)) != 1) {
+    gpr_log(GPR_ERROR, "JWT signature verification failed.");
+    goto end;
+  }
+  result = 1;
+
+end:
+  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
+  return result;
+}
+
+static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
+                              const grpc_httpcli_response *response) {
+  grpc_json *json = json_from_http(response);
+  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+  EVP_PKEY *verification_key = NULL;
+  grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
+  grpc_jwt_claims *claims = NULL;
+
+  if (json == NULL) {
+    status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
+    goto end;
+  }
+  verification_key =
+      find_verification_key(json, ctx->header->alg, ctx->header->kid);
+  if (verification_key == NULL) {
+    gpr_log(GPR_ERROR, "Could not find verification key with kid %s.",
+            ctx->header->kid);
+    status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
+    goto end;
+  }
+
+  if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature,
+                            ctx->signed_data)) {
+    status = GRPC_JWT_VERIFIER_BAD_SIGNATURE;
+    goto end;
+  }
+
+  status = grpc_jwt_claims_check(ctx->claims, ctx->audience);
+  if (status == GRPC_JWT_VERIFIER_OK) {
+    /* Pass ownership. */
+    claims = ctx->claims;
+    ctx->claims = NULL;
+  }
+
+end:
+  if (json != NULL) grpc_json_destroy(json);
+  if (verification_key != NULL) EVP_PKEY_free(verification_key);
+  ctx->user_cb(ctx->user_data, status, claims);
+  verifier_cb_ctx_destroy(ctx);
+}
+
+static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
+                                       const grpc_httpcli_response *response) {
+  const grpc_json *cur;
+  grpc_json *json = json_from_http(response);
+  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+  grpc_httpcli_request req;
+  const char *jwks_uri;
+
+  /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
+  if (json == NULL) goto error;
+  cur = find_property_by_name(json, "jwks_uri");
+  if (cur == NULL) {
+    gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
+    goto error;
+  }
+  jwks_uri = validate_string_field(cur, "jwks_uri");
+  if (jwks_uri == NULL) goto error;
+  if (strstr(jwks_uri, "https://") != jwks_uri) {
+    gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
+    goto error;
+  }
+  jwks_uri += 8;
+  req.handshaker = &grpc_httpcli_ssl;
+  req.host = gpr_strdup(jwks_uri);
+  req.http.path = strchr(jwks_uri, '/');
+  if (req.http.path == NULL) {
+    req.http.path = "";
+  } else {
+    *(req.host + (req.http.path - jwks_uri)) = '\0';
+  }
+  grpc_httpcli_get(
+      exec_ctx, &ctx->verifier->http_ctx, &ctx->pops, &req,
+      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
+      on_keys_retrieved, ctx);
+  grpc_json_destroy(json);
+  gpr_free(req.host);
+  return;
+
+error:
+  if (json != NULL) grpc_json_destroy(json);
+  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
+  verifier_cb_ctx_destroy(ctx);
+}
+
+static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
+                                               const char *email_domain) {
+  size_t i;
+  if (v->mappings == NULL) return NULL;
+  for (i = 0; i < v->num_mappings; i++) {
+    if (strcmp(email_domain, v->mappings[i].email_domain) == 0) {
+      return &v->mappings[i];
+    }
+  }
+  return NULL;
+}
+
+static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
+                                 const char *key_url_prefix) {
+  email_key_mapping *mapping = verifier_get_mapping(v, email_domain);
+  GPR_ASSERT(v->num_mappings < v->allocated_mappings);
+  if (mapping != NULL) {
+    gpr_free(mapping->key_url_prefix);
+    mapping->key_url_prefix = gpr_strdup(key_url_prefix);
+    return;
+  }
+  v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain);
+  v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix);
+  v->num_mappings++;
+  GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
+}
+
+/* Takes ownership of ctx. */
+static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
+                                    verifier_cb_ctx *ctx) {
+  const char *at_sign;
+  grpc_httpcli_response_cb http_cb;
+  char *path_prefix = NULL;
+  const char *iss;
+  grpc_httpcli_request req;
+  memset(&req, 0, sizeof(grpc_httpcli_request));
+  req.handshaker = &grpc_httpcli_ssl;
+
+  GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
+  iss = ctx->claims->iss;
+  if (ctx->header->kid == NULL) {
+    gpr_log(GPR_ERROR, "Missing kid in jose header.");
+    goto error;
+  }
+  if (iss == NULL) {
+    gpr_log(GPR_ERROR, "Missing iss in claims.");
+    goto error;
+  }
+
+  /* This code relies on:
+     https://openid.net/specs/openid-connect-discovery-1_0.html
+     Nobody seems to implement the account/email/webfinger part 2. of the spec
+     so we will rely instead on email/url mappings if we detect such an issuer.
+     Part 4, on the other hand is implemented by both google and salesforce. */
+
+  /* Very non-sophisticated way to detect an email address. Should be good
+     enough for now... */
+  at_sign = strchr(iss, '@');
+  if (at_sign != NULL) {
+    email_key_mapping *mapping;
+    const char *email_domain = at_sign + 1;
+    GPR_ASSERT(ctx->verifier != NULL);
+    mapping = verifier_get_mapping(ctx->verifier, email_domain);
+    if (mapping == NULL) {
+      gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
+      goto error;
+    }
+    req.host = gpr_strdup(mapping->key_url_prefix);
+    path_prefix = strchr(req.host, '/');
+    if (path_prefix == NULL) {
+      gpr_asprintf(&req.http.path, "/%s", iss);
+    } else {
+      *(path_prefix++) = '\0';
+      gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
+    }
+    http_cb = on_keys_retrieved;
+  } else {
+    req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
+    path_prefix = strchr(req.host, '/');
+    if (path_prefix == NULL) {
+      req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
+    } else {
+      *(path_prefix++) = 0;
+      gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
+                   GRPC_OPENID_CONFIG_URL_SUFFIX);
+    }
+    http_cb = on_openid_config_retrieved;
+  }
+
+  grpc_httpcli_get(
+      exec_ctx, &ctx->verifier->http_ctx, &ctx->pops, &req,
+      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
+      http_cb, ctx);
+  gpr_free(req.host);
+  gpr_free(req.http.path);
+  return;
+
+error:
+  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
+  verifier_cb_ctx_destroy(ctx);
+}
+
+void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
+                              grpc_jwt_verifier *verifier,
+                              grpc_pollset *pollset, const char *jwt,
+                              const char *audience,
+                              grpc_jwt_verification_done_cb cb,
+                              void *user_data) {
+  const char *dot = NULL;
+  grpc_json *json;
+  jose_header *header = NULL;
+  grpc_jwt_claims *claims = NULL;
+  gpr_slice header_buffer;
+  gpr_slice claims_buffer;
+  gpr_slice signature;
+  size_t signed_jwt_len;
+  const char *cur = jwt;
+
+  GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
+  dot = strchr(cur, '.');
+  if (dot == NULL) goto error;
+  json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer);
+  if (json == NULL) goto error;
+  header = jose_header_from_json(json, header_buffer);
+  if (header == NULL) goto error;
+
+  cur = dot + 1;
+  dot = strchr(cur, '.');
+  if (dot == NULL) goto error;
+  json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
+  if (json == NULL) goto error;
+  claims = grpc_jwt_claims_from_json(json, claims_buffer);
+  if (claims == NULL) goto error;
+
+  signed_jwt_len = (size_t)(dot - jwt);
+  cur = dot + 1;
+  signature = grpc_base64_decode(cur, 1);
+  if (GPR_SLICE_IS_EMPTY(signature)) goto error;
+  retrieve_key_and_verify(
+      exec_ctx,
+      verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
+                             signature, jwt, signed_jwt_len, user_data, cb));
+  return;
+
+error:
+  if (header != NULL) jose_header_destroy(header);
+  if (claims != NULL) grpc_jwt_claims_destroy(claims);
+  cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
+}
+
+grpc_jwt_verifier *grpc_jwt_verifier_create(
+    const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
+    size_t num_mappings) {
+  grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier));
+  memset(v, 0, sizeof(grpc_jwt_verifier));
+  grpc_httpcli_context_init(&v->http_ctx);
+
+  /* We know at least of one mapping. */
+  v->allocated_mappings = 1 + num_mappings;
+  v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping));
+  verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN,
+                       GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX);
+  /* User-Provided mappings. */
+  if (mappings != NULL) {
+    size_t i;
+    for (i = 0; i < num_mappings; i++) {
+      verifier_put_mapping(v, mappings[i].email_domain,
+                           mappings[i].key_url_prefix);
+    }
+  }
+  return v;
+}
+
+void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
+  size_t i;
+  if (v == NULL) return;
+  grpc_httpcli_context_destroy(&v->http_ctx);
+  if (v->mappings != NULL) {
+    for (i = 0; i < v->num_mappings; i++) {
+      gpr_free(v->mappings[i].email_domain);
+      gpr_free(v->mappings[i].key_url_prefix);
+    }
+    gpr_free(v->mappings);
+  }
+  gpr_free(v);
+}
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h
new file mode 100644
index 0000000..b0f6d1c
--- /dev/null
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -0,0 +1,136 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H
+
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/json/json.h"
+
+#include <grpc/support/slice.h>
+#include <grpc/support/time.h>
+
+/* --- Constants. --- */
+
+#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \
+  "developer.gserviceaccount.com"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \
+  "www.googleapis.com/robot/v1/metadata/x509"
+
+/* --- grpc_jwt_verifier_status. --- */
+
+typedef enum {
+  GRPC_JWT_VERIFIER_OK = 0,
+  GRPC_JWT_VERIFIER_BAD_SIGNATURE,
+  GRPC_JWT_VERIFIER_BAD_FORMAT,
+  GRPC_JWT_VERIFIER_BAD_AUDIENCE,
+  GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
+  GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE,
+  GRPC_JWT_VERIFIER_GENERIC_ERROR
+} grpc_jwt_verifier_status;
+
+const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status);
+
+/* --- grpc_jwt_claims. --- */
+
+typedef struct grpc_jwt_claims grpc_jwt_claims;
+
+void grpc_jwt_claims_destroy(grpc_jwt_claims *claims);
+
+/* Returns the whole JSON tree of the claims. */
+const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims);
+
+/* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */
+const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims);
+const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims);
+gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims);
+
+/* --- grpc_jwt_verifier. --- */
+
+typedef struct grpc_jwt_verifier grpc_jwt_verifier;
+
+typedef struct {
+  /* The email domain is the part after the @ sign. */
+  const char *email_domain;
+
+  /* The key url prefix will be used to get the public key from the issuer:
+     https://<key_url_prefix>/<issuer_email>
+     Therefore the key_url_prefix must NOT contain https://. */
+  const char *key_url_prefix;
+} grpc_jwt_verifier_email_domain_key_url_mapping;
+
+/* Globals to control the verifier. Not thread-safe. */
+extern gpr_timespec grpc_jwt_verifier_clock_skew;
+extern gpr_timespec grpc_jwt_verifier_max_delay;
+
+/* The verifier can be created with some custom mappings to help with key
+   discovery in the case where the issuer is an email address.
+   mappings can be NULL in which case num_mappings MUST be 0.
+   A verifier object has one built-in mapping (unless overridden):
+   GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN ->
+   GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/
+grpc_jwt_verifier *grpc_jwt_verifier_create(
+    const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
+    size_t num_mappings);
+
+/*The verifier must not be destroyed if there are still outstanding callbacks.*/
+void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier);
+
+/* User provided callback that will be called when the verification of the JWT
+   is done (maybe in another thread).
+   It is the responsibility of the callee to call grpc_jwt_claims_destroy on
+   the claims. */
+typedef void (*grpc_jwt_verification_done_cb)(void *user_data,
+                                              grpc_jwt_verifier_status status,
+                                              grpc_jwt_claims *claims);
+
+/* Verifies for the JWT for the given expected audience. */
+void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
+                              grpc_jwt_verifier *verifier,
+                              grpc_pollset *pollset, const char *jwt,
+                              const char *audience,
+                              grpc_jwt_verification_done_cb cb,
+                              void *user_data);
+
+/* --- TESTING ONLY exposed functions. --- */
+
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer);
+grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
+                                               const char *audience);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H */
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
new file mode 100644
index 0000000..131aa69
--- /dev/null
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -0,0 +1,428 @@
+/*
+ *
+ * Copyright 2015, 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/security/credentials/oauth2/oauth2_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/security/util/json_util.h"
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+//
+// Auth Refresh Token.
+//
+
+int grpc_auth_refresh_token_is_valid(
+    const grpc_auth_refresh_token *refresh_token) {
+  return (refresh_token != NULL) &&
+         strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
+}
+
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+    const grpc_json *json) {
+  grpc_auth_refresh_token result;
+  const char *prop_value;
+  int success = 0;
+
+  memset(&result, 0, sizeof(grpc_auth_refresh_token));
+  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (json == NULL) {
+    gpr_log(GPR_ERROR, "Invalid json.");
+    goto end;
+  }
+
+  prop_value = grpc_json_get_string_property(json, "type");
+  if (prop_value == NULL ||
+      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) {
+    goto end;
+  }
+  result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER;
+
+  if (!grpc_copy_json_string_property(json, "client_secret",
+                                      &result.client_secret) ||
+      !grpc_copy_json_string_property(json, "client_id", &result.client_id) ||
+      !grpc_copy_json_string_property(json, "refresh_token",
+                                      &result.refresh_token)) {
+    goto end;
+  }
+  success = 1;
+
+end:
+  if (!success) grpc_auth_refresh_token_destruct(&result);
+  return result;
+}
+
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+    const char *json_string) {
+  char *scratchpad = gpr_strdup(json_string);
+  grpc_json *json = grpc_json_parse_string(scratchpad);
+  grpc_auth_refresh_token result =
+      grpc_auth_refresh_token_create_from_json(json);
+  if (json != NULL) grpc_json_destroy(json);
+  gpr_free(scratchpad);
+  return result;
+}
+
+void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
+  if (refresh_token == NULL) return;
+  refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (refresh_token->client_id != NULL) {
+    gpr_free(refresh_token->client_id);
+    refresh_token->client_id = NULL;
+  }
+  if (refresh_token->client_secret != NULL) {
+    gpr_free(refresh_token->client_secret);
+    refresh_token->client_secret = NULL;
+  }
+  if (refresh_token->refresh_token != NULL) {
+    gpr_free(refresh_token->refresh_token);
+    refresh_token->refresh_token = NULL;
+  }
+}
+
+//
+// Oauth2 Token Fetcher credentials.
+//
+
+static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
+  grpc_oauth2_token_fetcher_credentials *c =
+      (grpc_oauth2_token_fetcher_credentials *)creds;
+  grpc_credentials_md_store_unref(c->access_token_md);
+  gpr_mu_destroy(&c->mu);
+  grpc_httpcli_context_destroy(&c->httpcli_context);
+}
+
+grpc_credentials_status
+grpc_oauth2_token_fetcher_credentials_parse_server_response(
+    const grpc_http_response *response, grpc_credentials_md_store **token_md,
+    gpr_timespec *token_lifetime) {
+  char *null_terminated_body = NULL;
+  char *new_access_token = NULL;
+  grpc_credentials_status status = GRPC_CREDENTIALS_OK;
+  grpc_json *json = NULL;
+
+  if (response == NULL) {
+    gpr_log(GPR_ERROR, "Received NULL response.");
+    status = GRPC_CREDENTIALS_ERROR;
+    goto end;
+  }
+
+  if (response->body_length > 0) {
+    null_terminated_body = gpr_malloc(response->body_length + 1);
+    null_terminated_body[response->body_length] = '\0';
+    memcpy(null_terminated_body, response->body, response->body_length);
+  }
+
+  if (response->status != 200) {
+    gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
+            response->status,
+            null_terminated_body != NULL ? null_terminated_body : "");
+    status = GRPC_CREDENTIALS_ERROR;
+    goto end;
+  } else {
+    grpc_json *access_token = NULL;
+    grpc_json *token_type = NULL;
+    grpc_json *expires_in = NULL;
+    grpc_json *ptr;
+    json = grpc_json_parse_string(null_terminated_body);
+    if (json == NULL) {
+      gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
+      status = GRPC_CREDENTIALS_ERROR;
+      goto end;
+    }
+    if (json->type != GRPC_JSON_OBJECT) {
+      gpr_log(GPR_ERROR, "Response should be a JSON object");
+      status = GRPC_CREDENTIALS_ERROR;
+      goto end;
+    }
+    for (ptr = json->child; ptr; ptr = ptr->next) {
+      if (strcmp(ptr->key, "access_token") == 0) {
+        access_token = ptr;
+      } else if (strcmp(ptr->key, "token_type") == 0) {
+        token_type = ptr;
+      } else if (strcmp(ptr->key, "expires_in") == 0) {
+        expires_in = ptr;
+      }
+    }
+    if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
+      gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
+      status = GRPC_CREDENTIALS_ERROR;
+      goto end;
+    }
+    if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
+      gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
+      status = GRPC_CREDENTIALS_ERROR;
+      goto end;
+    }
+    if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
+      gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
+      status = GRPC_CREDENTIALS_ERROR;
+      goto end;
+    }
+    gpr_asprintf(&new_access_token, "%s %s", token_type->value,
+                 access_token->value);
+    token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
+    token_lifetime->tv_nsec = 0;
+    token_lifetime->clock_type = GPR_TIMESPAN;
+    if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
+    *token_md = grpc_credentials_md_store_create(1);
+    grpc_credentials_md_store_add_cstrings(
+        *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
+    status = GRPC_CREDENTIALS_OK;
+  }
+
+end:
+  if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
+    grpc_credentials_md_store_unref(*token_md);
+    *token_md = NULL;
+  }
+  if (null_terminated_body != NULL) gpr_free(null_terminated_body);
+  if (new_access_token != NULL) gpr_free(new_access_token);
+  if (json != NULL) grpc_json_destroy(json);
+  return status;
+}
+
+static void on_oauth2_token_fetcher_http_response(
+    grpc_exec_ctx *exec_ctx, void *user_data,
+    const grpc_http_response *response) {
+  grpc_credentials_metadata_request *r =
+      (grpc_credentials_metadata_request *)user_data;
+  grpc_oauth2_token_fetcher_credentials *c =
+      (grpc_oauth2_token_fetcher_credentials *)r->creds;
+  gpr_timespec token_lifetime;
+  grpc_credentials_status status;
+
+  gpr_mu_lock(&c->mu);
+  status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
+      response, &c->access_token_md, &token_lifetime);
+  if (status == GRPC_CREDENTIALS_OK) {
+    c->token_expiration =
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
+    r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
+          c->access_token_md->num_entries, status);
+  } else {
+    c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
+    r->cb(exec_ctx, r->user_data, NULL, 0, status);
+  }
+  gpr_mu_unlock(&c->mu);
+  grpc_credentials_metadata_request_destroy(r);
+}
+
+static void oauth2_token_fetcher_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pops *pops, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
+  grpc_oauth2_token_fetcher_credentials *c =
+      (grpc_oauth2_token_fetcher_credentials *)creds;
+  gpr_timespec refresh_threshold = gpr_time_from_seconds(
+      GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
+  grpc_credentials_md_store *cached_access_token_md = NULL;
+  {
+    gpr_mu_lock(&c->mu);
+    if (c->access_token_md != NULL &&
+        (gpr_time_cmp(
+             gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
+             refresh_threshold) > 0)) {
+      cached_access_token_md =
+          grpc_credentials_md_store_ref(c->access_token_md);
+    }
+    gpr_mu_unlock(&c->mu);
+  }
+  if (cached_access_token_md != NULL) {
+    cb(exec_ctx, user_data, cached_access_token_md->entries,
+       cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
+    grpc_credentials_md_store_unref(cached_access_token_md);
+  } else {
+    c->fetch_func(
+        exec_ctx,
+        grpc_credentials_metadata_request_create(creds, cb, user_data),
+        &c->httpcli_context, pops, on_oauth2_token_fetcher_http_response,
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
+  }
+}
+
+static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
+                                      grpc_fetch_oauth2_func fetch_func) {
+  memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
+  gpr_ref_init(&c->base.refcount, 1);
+  gpr_mu_init(&c->mu);
+  c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
+  c->fetch_func = fetch_func;
+  grpc_httpcli_context_init(&c->httpcli_context);
+}
+
+//
+//  Google Compute Engine credentials.
+//
+
+static grpc_call_credentials_vtable compute_engine_vtable = {
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
+
+static void compute_engine_fetch_oauth2(
+    grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
+    grpc_httpcli_context *httpcli_context, grpc_pops* pops,
+    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+  grpc_http_header header = {"Metadata-Flavor", "Google"};
+  grpc_httpcli_request request;
+  memset(&request, 0, sizeof(grpc_httpcli_request));
+  request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
+  request.http.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
+  request.http.hdr_count = 1;
+  request.http.hdrs = &header;
+  grpc_httpcli_get(exec_ctx, httpcli_context, pops, &request, deadline,
+                   response_cb, metadata_req);
+}
+
+grpc_call_credentials *grpc_google_compute_engine_credentials_create(
+    void *reserved) {
+  grpc_oauth2_token_fetcher_credentials *c =
+      gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
+  GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1,
+                 (reserved));
+  GPR_ASSERT(reserved == NULL);
+  init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
+  c->base.vtable = &compute_engine_vtable;
+  return &c->base;
+}
+
+//
+// Google Refresh Token credentials.
+//
+
+static void refresh_token_destruct(grpc_call_credentials *creds) {
+  grpc_google_refresh_token_credentials *c =
+      (grpc_google_refresh_token_credentials *)creds;
+  grpc_auth_refresh_token_destruct(&c->refresh_token);
+  oauth2_token_fetcher_destruct(&c->base.base);
+}
+
+static grpc_call_credentials_vtable refresh_token_vtable = {
+    refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
+
+static void refresh_token_fetch_oauth2(
+    grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
+    grpc_httpcli_context *httpcli_context, grpc_pops* pops,
+    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+  grpc_google_refresh_token_credentials *c =
+      (grpc_google_refresh_token_credentials *)metadata_req->creds;
+  grpc_http_header header = {"Content-Type",
+                             "application/x-www-form-urlencoded"};
+  grpc_httpcli_request request;
+  char *body = NULL;
+  gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
+               c->refresh_token.client_id, c->refresh_token.client_secret,
+               c->refresh_token.refresh_token);
+  memset(&request, 0, sizeof(grpc_httpcli_request));
+  request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
+  request.http.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
+  request.http.hdr_count = 1;
+  request.http.hdrs = &header;
+  request.handshaker = &grpc_httpcli_ssl;
+  grpc_httpcli_post(exec_ctx, httpcli_context, pops, &request, body,
+                    strlen(body), deadline, response_cb, metadata_req);
+  gpr_free(body);
+}
+
+grpc_call_credentials *
+grpc_refresh_token_credentials_create_from_auth_refresh_token(
+    grpc_auth_refresh_token refresh_token) {
+  grpc_google_refresh_token_credentials *c;
+  if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
+    gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
+    return NULL;
+  }
+  c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
+  memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
+  init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
+  c->base.base.vtable = &refresh_token_vtable;
+  c->refresh_token = refresh_token;
+  return &c->base.base;
+}
+
+grpc_call_credentials *grpc_google_refresh_token_credentials_create(
+    const char *json_refresh_token, void *reserved) {
+  GRPC_API_TRACE(
+      "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
+      "reserved=%p)",
+      2, (json_refresh_token, reserved));
+  GPR_ASSERT(reserved == NULL);
+  return grpc_refresh_token_credentials_create_from_auth_refresh_token(
+      grpc_auth_refresh_token_create_from_string(json_refresh_token));
+}
+
+//
+// Oauth2 Access Token credentials.
+//
+
+static void access_token_destruct(grpc_call_credentials *creds) {
+  grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
+  grpc_credentials_md_store_unref(c->access_token_md);
+}
+
+static void access_token_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pops* pops, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
+  grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
+  cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
+}
+
+static grpc_call_credentials_vtable access_token_vtable = {
+    access_token_destruct, access_token_get_request_metadata};
+
+grpc_call_credentials *grpc_access_token_credentials_create(
+    const char *access_token, void *reserved) {
+  grpc_access_token_credentials *c =
+      gpr_malloc(sizeof(grpc_access_token_credentials));
+  char *token_md_value;
+  GRPC_API_TRACE(
+      "grpc_access_token_credentials_create(access_token=%s, "
+      "reserved=%p)",
+      2, (access_token, reserved));
+  GPR_ASSERT(reserved == NULL);
+  memset(c, 0, sizeof(grpc_access_token_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
+  c->base.vtable = &access_token_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->access_token_md = grpc_credentials_md_store_create(1);
+  gpr_asprintf(&token_md_value, "Bearer %s", access_token);
+  grpc_credentials_md_store_add_cstrings(
+      c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
+  gpr_free(token_md_value);
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
new file mode 100644
index 0000000..2ae37f5
--- /dev/null
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H
+
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/security/credentials/credentials.h"
+
+// auth_refresh_token parsing.
+typedef struct {
+  const char *type;
+  char *client_id;
+  char *client_secret;
+  char *refresh_token;
+} grpc_auth_refresh_token;
+
+/// Returns 1 if the object is valid, 0 otherwise.
+int grpc_auth_refresh_token_is_valid(
+    const grpc_auth_refresh_token *refresh_token);
+
+/// Creates a refresh token object from string. Returns an invalid object if a
+/// parsing error has been encountered.
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+    const char *json_string);
+
+/// Creates a refresh token object from parsed json. Returns an invalid object
+/// if a parsing error has been encountered.
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
+    const grpc_json *json);
+
+/// Destructs the object.
+void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
+
+// -- Oauth2 Token Fetcher credentials --
+//
+//  This object is a base for credentials that need to acquire an oauth2 token
+//  from an http service.
+
+typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
+                                       grpc_credentials_metadata_request *req,
+                                       grpc_httpcli_context *http_context,
+                                       grpc_pops *pops,
+                                       grpc_httpcli_response_cb response_cb,
+                                       gpr_timespec deadline);
+typedef struct {
+  grpc_call_credentials base;
+  gpr_mu mu;
+  grpc_credentials_md_store *access_token_md;
+  gpr_timespec token_expiration;
+  grpc_httpcli_context httpcli_context;
+  grpc_fetch_oauth2_func fetch_func;
+} grpc_oauth2_token_fetcher_credentials;
+
+// Google refresh token credentials.
+typedef struct {
+  grpc_oauth2_token_fetcher_credentials base;
+  grpc_auth_refresh_token refresh_token;
+} grpc_google_refresh_token_credentials;
+
+// Access token credentials.
+typedef struct {
+  grpc_call_credentials base;
+  grpc_credentials_md_store *access_token_md;
+} grpc_access_token_credentials;
+
+// Private constructor for refresh token credentials from an already parsed
+// refresh token. Takes ownership of the refresh token.
+grpc_call_credentials *
+grpc_refresh_token_credentials_create_from_auth_refresh_token(
+    grpc_auth_refresh_token token);
+
+// Exposed for testing only.
+grpc_credentials_status
+grpc_oauth2_token_fetcher_credentials_parse_server_response(
+    const struct grpc_http_response *response,
+    grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
new file mode 100644
index 0000000..348f4c9
--- /dev/null
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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/security/credentials/plugin/plugin_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+
+typedef struct {
+  void *user_data;
+  grpc_credentials_metadata_cb cb;
+} grpc_metadata_plugin_request;
+
+static void plugin_destruct(grpc_call_credentials *creds) {
+  grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+  if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
+    c->plugin.destroy(c->plugin.state);
+  }
+}
+
+static void plugin_md_request_metadata_ready(void *request,
+                                             const grpc_metadata *md,
+                                             size_t num_md,
+                                             grpc_status_code status,
+                                             const char *error_details) {
+  /* called from application code */
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
+  if (status != GRPC_STATUS_OK) {
+    if (error_details != NULL) {
+      gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
+              error_details);
+    }
+    r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+  } else {
+    size_t i;
+    grpc_credentials_md *md_array = NULL;
+    if (num_md > 0) {
+      md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
+      for (i = 0; i < num_md; i++) {
+        md_array[i].key = gpr_slice_from_copied_string(md[i].key);
+        md_array[i].value =
+            gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
+      }
+    }
+    r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
+    if (md_array != NULL) {
+      for (i = 0; i < num_md; i++) {
+        gpr_slice_unref(md_array[i].key);
+        gpr_slice_unref(md_array[i].value);
+      }
+      gpr_free(md_array);
+    }
+  }
+  gpr_free(r);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                        grpc_call_credentials *creds,
+                                        grpc_pops *pops,
+                                        grpc_auth_metadata_context context,
+                                        grpc_credentials_metadata_cb cb,
+                                        void *user_data) {
+  grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+  if (c->plugin.get_metadata != NULL) {
+    grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
+    memset(request, 0, sizeof(*request));
+    request->user_data = user_data;
+    request->cb = cb;
+    c->plugin.get_metadata(c->plugin.state, context,
+                           plugin_md_request_metadata_ready, request);
+  } else {
+    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+  }
+}
+
+static grpc_call_credentials_vtable plugin_vtable = {
+    plugin_destruct, plugin_get_request_metadata};
+
+grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
+    grpc_metadata_credentials_plugin plugin, void *reserved) {
+  grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+  GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
+                 (reserved));
+  GPR_ASSERT(reserved == NULL);
+  memset(c, 0, sizeof(*c));
+  c->base.type = plugin.type;
+  c->base.vtable = &plugin_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->plugin = plugin;
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h
new file mode 100644
index 0000000..89073cb
--- /dev/null
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+typedef struct {
+  grpc_call_credentials base;
+  grpc_metadata_credentials_plugin plugin;
+  grpc_credentials_md_store *plugin_md;
+} grpc_plugin_credentials;
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c
new file mode 100644
index 0000000..545bca9
--- /dev/null
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c
@@ -0,0 +1,240 @@
+/*
+ *
+ * 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/security/credentials/ssl/ssl_credentials.h"
+
+#include <string.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/surface/api_trace.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+//
+// Utils
+//
+
+static void ssl_copy_key_material(const char *input, unsigned char **output,
+                                  size_t *output_size) {
+  *output_size = strlen(input);
+  *output = gpr_malloc(*output_size);
+  memcpy(*output, input, *output_size);
+}
+
+//
+// SSL Channel Credentials.
+//
+
+static void ssl_destruct(grpc_channel_credentials *creds) {
+  grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
+  if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
+  if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
+  if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
+}
+
+static grpc_security_status ssl_create_security_connector(
+    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
+  grpc_security_status status = GRPC_SECURITY_OK;
+  size_t i = 0;
+  const char *overridden_target_name = NULL;
+  grpc_arg new_arg;
+
+  for (i = 0; args && i < args->num_args; i++) {
+    grpc_arg *arg = &args->args[i];
+    if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
+        arg->type == GRPC_ARG_STRING) {
+      overridden_target_name = arg->value.string;
+      break;
+    }
+  }
+  status = grpc_ssl_channel_security_connector_create(
+      call_creds, &c->config, target, overridden_target_name, sc);
+  if (status != GRPC_SECURITY_OK) {
+    return status;
+  }
+  new_arg.type = GRPC_ARG_STRING;
+  new_arg.key = GRPC_ARG_HTTP2_SCHEME;
+  new_arg.value.string = "https";
+  *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
+  return status;
+}
+
+static grpc_channel_credentials_vtable ssl_vtable = {
+    ssl_destruct, ssl_create_security_connector};
+
+static void ssl_build_config(const char *pem_root_certs,
+                             grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
+                             grpc_ssl_config *config) {
+  if (pem_root_certs != NULL) {
+    ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
+                          &config->pem_root_certs_size);
+  }
+  if (pem_key_cert_pair != NULL) {
+    GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
+    GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
+    ssl_copy_key_material(pem_key_cert_pair->private_key,
+                          &config->pem_private_key,
+                          &config->pem_private_key_size);
+    ssl_copy_key_material(pem_key_cert_pair->cert_chain,
+                          &config->pem_cert_chain,
+                          &config->pem_cert_chain_size);
+  }
+}
+
+grpc_channel_credentials *grpc_ssl_credentials_create(
+    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
+    void *reserved) {
+  grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
+  GRPC_API_TRACE(
+      "grpc_ssl_credentials_create(pem_root_certs=%s, "
+      "pem_key_cert_pair=%p, "
+      "reserved=%p)",
+      3, (pem_root_certs, pem_key_cert_pair, reserved));
+  GPR_ASSERT(reserved == NULL);
+  memset(c, 0, sizeof(grpc_ssl_credentials));
+  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
+  c->base.vtable = &ssl_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
+  return &c->base;
+}
+
+//
+// SSL Server Credentials.
+//
+
+static void ssl_server_destruct(grpc_server_credentials *creds) {
+  grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
+  size_t i;
+  for (i = 0; i < c->config.num_key_cert_pairs; i++) {
+    if (c->config.pem_private_keys[i] != NULL) {
+      gpr_free(c->config.pem_private_keys[i]);
+    }
+    if (c->config.pem_cert_chains[i] != NULL) {
+      gpr_free(c->config.pem_cert_chains[i]);
+    }
+  }
+  if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
+  if (c->config.pem_private_keys_sizes != NULL) {
+    gpr_free(c->config.pem_private_keys_sizes);
+  }
+  if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
+  if (c->config.pem_cert_chains_sizes != NULL) {
+    gpr_free(c->config.pem_cert_chains_sizes);
+  }
+  if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
+}
+
+static grpc_security_status ssl_server_create_security_connector(
+    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
+  grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
+  return grpc_ssl_server_security_connector_create(&c->config, sc);
+}
+
+static grpc_server_credentials_vtable ssl_server_vtable = {
+    ssl_server_destruct, ssl_server_create_security_connector};
+
+static void ssl_build_server_config(
+    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+    size_t num_key_cert_pairs,
+    grpc_ssl_client_certificate_request_type client_certificate_request,
+    grpc_ssl_server_config *config) {
+  size_t i;
+  config->client_certificate_request = client_certificate_request;
+  if (pem_root_certs != NULL) {
+    ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
+                          &config->pem_root_certs_size);
+  }
+  if (num_key_cert_pairs > 0) {
+    GPR_ASSERT(pem_key_cert_pairs != NULL);
+    config->pem_private_keys =
+        gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
+    config->pem_cert_chains =
+        gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
+    config->pem_private_keys_sizes =
+        gpr_malloc(num_key_cert_pairs * sizeof(size_t));
+    config->pem_cert_chains_sizes =
+        gpr_malloc(num_key_cert_pairs * sizeof(size_t));
+  }
+  config->num_key_cert_pairs = num_key_cert_pairs;
+  for (i = 0; i < num_key_cert_pairs; i++) {
+    GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
+    GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
+    ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
+                          &config->pem_private_keys[i],
+                          &config->pem_private_keys_sizes[i]);
+    ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
+                          &config->pem_cert_chains[i],
+                          &config->pem_cert_chains_sizes[i]);
+  }
+}
+
+grpc_server_credentials *grpc_ssl_server_credentials_create(
+    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+    size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
+  return grpc_ssl_server_credentials_create_ex(
+      pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
+      force_client_auth
+          ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+          : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+      reserved);
+}
+
+grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
+    const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+    size_t num_key_cert_pairs,
+    grpc_ssl_client_certificate_request_type client_certificate_request,
+    void *reserved) {
+  grpc_ssl_server_credentials *c =
+      gpr_malloc(sizeof(grpc_ssl_server_credentials));
+  GRPC_API_TRACE(
+      "grpc_ssl_server_credentials_create_ex("
+      "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
+      "client_certificate_request=%d, reserved=%p)",
+      5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
+          client_certificate_request, reserved));
+  GPR_ASSERT(reserved == NULL);
+  memset(c, 0, sizeof(grpc_ssl_server_credentials));
+  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->base.vtable = &ssl_server_vtable;
+  ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
+                          num_key_cert_pairs, client_certificate_request,
+                          &c->config);
+  return &c->base;
+}
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.h b/src/core/lib/security/credentials/ssl/ssl_credentials.h
new file mode 100644
index 0000000..f23dbdb
--- /dev/null
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H
+
+#include "src/core/lib/security/credentials/credentials.h"
+
+typedef struct {
+  grpc_channel_credentials base;
+  grpc_ssl_config config;
+} grpc_ssl_credentials;
+
+typedef struct {
+  grpc_server_credentials base;
+  grpc_ssl_server_config config;
+} grpc_ssl_server_credentials;
+
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials_metadata.c b/src/core/lib/security/credentials_metadata.c
deleted file mode 100644
index bd00194..0000000
--- a/src/core/lib/security/credentials_metadata.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/credentials.h"
-
-#include <grpc/support/alloc.h>
-
-#include <string.h>
-
-static void store_ensure_capacity(grpc_credentials_md_store *store) {
-  if (store->num_entries == store->allocated) {
-    store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
-    store->entries = gpr_realloc(
-        store->entries, store->allocated * sizeof(grpc_credentials_md));
-  }
-}
-
-grpc_credentials_md_store *grpc_credentials_md_store_create(
-    size_t initial_capacity) {
-  grpc_credentials_md_store *store =
-      gpr_malloc(sizeof(grpc_credentials_md_store));
-  memset(store, 0, sizeof(grpc_credentials_md_store));
-  if (initial_capacity > 0) {
-    store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
-    store->allocated = initial_capacity;
-  }
-  gpr_ref_init(&store->refcount, 1);
-  return store;
-}
-
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
-                                   gpr_slice key, gpr_slice value) {
-  if (store == NULL) return;
-  store_ensure_capacity(store);
-  store->entries[store->num_entries].key = gpr_slice_ref(key);
-  store->entries[store->num_entries].value = gpr_slice_ref(value);
-  store->num_entries++;
-}
-
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
-                                            const char *key,
-                                            const char *value) {
-  if (store == NULL) return;
-  store_ensure_capacity(store);
-  store->entries[store->num_entries].key = gpr_slice_from_copied_string(key);
-  store->entries[store->num_entries].value =
-      gpr_slice_from_copied_string(value);
-  store->num_entries++;
-}
-
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
-    grpc_credentials_md_store *store) {
-  if (store == NULL) return NULL;
-  gpr_ref(&store->refcount);
-  return store;
-}
-
-void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) {
-  if (store == NULL) return;
-  if (gpr_unref(&store->refcount)) {
-    if (store->entries != NULL) {
-      size_t i;
-      for (i = 0; i < store->num_entries; i++) {
-        gpr_slice_unref(store->entries[i].key);
-        gpr_slice_unref(store->entries[i].value);
-      }
-      gpr_free(store->entries);
-    }
-    gpr_free(store);
-  }
-}
diff --git a/src/core/lib/security/credentials_posix.c b/src/core/lib/security/credentials_posix.c
deleted file mode 100644
index a07de18..0000000
--- a/src/core/lib/security/credentials_posix.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_POSIX_FILE
-
-#include "src/core/lib/security/credentials.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/string.h"
-
-char *grpc_get_well_known_google_credentials_file_path_impl(void) {
-  char *result = NULL;
-  char *home = gpr_getenv("HOME");
-  if (home == NULL) {
-    gpr_log(GPR_ERROR, "Could not get HOME environment variable.");
-    return NULL;
-  }
-  gpr_asprintf(&result, "%s/.config/%s/%s", home,
-               GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY,
-               GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE);
-  gpr_free(home);
-  return result;
-}
-
-#endif /* GPR_POSIX_FILE */
diff --git a/src/core/lib/security/credentials_win32.c b/src/core/lib/security/credentials_win32.c
deleted file mode 100644
index d29847a..0000000
--- a/src/core/lib/security/credentials_win32.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <grpc/support/port_platform.h>
-
-#ifdef GPR_WIN32
-
-#include "src/core/lib/security/credentials.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/string.h"
-
-char *grpc_get_well_known_google_credentials_file_path_impl(void) {
-  char *result = NULL;
-  char *appdata_path = gpr_getenv("APPDATA");
-  if (appdata_path == NULL) {
-    gpr_log(GPR_ERROR, "Could not get APPDATA environment variable.");
-    return NULL;
-  }
-  gpr_asprintf(&result, "%s/%s/%s", appdata_path,
-               GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY,
-               GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE);
-  gpr_free(appdata_path);
-  return result;
-}
-
-#endif /* GPR_WIN32 */
diff --git a/src/core/lib/security/google_default_credentials.c b/src/core/lib/security/google_default_credentials.c
deleted file mode 100644
index 395a23b..0000000
--- a/src/core/lib/security/google_default_credentials.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/credentials.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/http/parser.h"
-#include "src/core/lib/iomgr/pops.h"
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
-#include "src/core/lib/surface/api_trace.h"
-
-/* -- Constants. -- */
-
-#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
-
-/* -- Default credentials. -- */
-
-static grpc_channel_credentials *default_credentials = NULL;
-static int compute_engine_detection_done = 0;
-static gpr_mu g_state_mu;
-static gpr_mu *g_polling_mu;
-static gpr_once g_once = GPR_ONCE_INIT;
-
-static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
-
-typedef struct {
-  grpc_pops pops;
-  int is_done;
-  int success;
-} compute_engine_detector;
-
-static void on_compute_engine_detection_http_response(
-    grpc_exec_ctx *exec_ctx, void *user_data,
-    const grpc_http_response *response) {
-  compute_engine_detector *detector = (compute_engine_detector *)user_data;
-  if (response != NULL && response->status == 200 && response->hdr_count > 0) {
-    /* Internet providers can return a generic response to all requests, so
-       it is necessary to check that metadata header is present also. */
-    size_t i;
-    for (i = 0; i < response->hdr_count; i++) {
-      grpc_http_header *header = &response->hdrs[i];
-      if (strcmp(header->key, "Metadata-Flavor") == 0 &&
-          strcmp(header->value, "Google") == 0) {
-        detector->success = 1;
-        break;
-      }
-    }
-  }
-  gpr_mu_lock(g_polling_mu);
-  detector->is_done = 1;
-  grpc_pollset_kick(grpc_pops_pollset(&detector->pops), NULL);
-  gpr_mu_unlock(g_polling_mu);
-}
-
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) {
-  grpc_pollset_destroy(p);
-}
-
-static int is_stack_running_on_compute_engine(void) {
-  compute_engine_detector detector;
-  grpc_httpcli_request request;
-  grpc_httpcli_context context;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_closure destroy_closure;
-
-  /* The http call is local. If it takes more than one sec, it is for sure not
-     on compute engine. */
-  gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
-
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
-  grpc_pollset_init(pollset, &g_polling_mu);
-  detector.pops = grpc_pops_create_from_pollset(pollset);
-  detector.is_done = 0;
-  detector.success = 0;
-
-  memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
-  request.http.path = "/";
-
-  grpc_httpcli_context_init(&context);
-
-  grpc_httpcli_get(
-      &exec_ctx, &context, &detector.pops, &request,
-      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
-      on_compute_engine_detection_http_response, &detector);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  /* Block until we get the response. This is not ideal but this should only be
-     called once for the lifetime of the process by the default credentials. */
-  gpr_mu_lock(g_polling_mu);
-  while (!detector.is_done) {
-    grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_pops_pollset(&detector.pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
-  }
-  gpr_mu_unlock(g_polling_mu);
-
-  grpc_httpcli_context_destroy(&context);
-  grpc_closure_init(&destroy_closure, destroy_pollset,
-                    grpc_pops_pollset(&detector.pops));
-  grpc_pollset_shutdown(&exec_ctx, grpc_pops_pollset(&detector.pops),
-                        &destroy_closure);
-  grpc_exec_ctx_finish(&exec_ctx);
-  g_polling_mu = NULL;
-
-  gpr_free(grpc_pops_pollset(&detector.pops));
-
-  return detector.success;
-}
-
-/* Takes ownership of creds_path if not NULL. */
-static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
-  grpc_json *json = NULL;
-  grpc_auth_json_key key;
-  grpc_auth_refresh_token token;
-  grpc_call_credentials *result = NULL;
-  gpr_slice creds_data = gpr_empty_slice();
-  int file_ok = 0;
-  if (creds_path == NULL) goto end;
-  creds_data = gpr_load_file(creds_path, 0, &file_ok);
-  if (!file_ok) goto end;
-  json = grpc_json_parse_string_with_len(
-      (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
-  if (json == NULL) goto end;
-
-  /* First, try an auth json key. */
-  key = grpc_auth_json_key_create_from_json(json);
-  if (grpc_auth_json_key_is_valid(&key)) {
-    result =
-        grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
-            key, grpc_max_auth_token_lifetime());
-    goto end;
-  }
-
-  /* Then try a refresh token if the auth json key was invalid. */
-  token = grpc_auth_refresh_token_create_from_json(json);
-  if (grpc_auth_refresh_token_is_valid(&token)) {
-    result =
-        grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
-    goto end;
-  }
-
-end:
-  if (creds_path != NULL) gpr_free(creds_path);
-  gpr_slice_unref(creds_data);
-  if (json != NULL) grpc_json_destroy(json);
-  return result;
-}
-
-grpc_channel_credentials *grpc_google_default_credentials_create(void) {
-  grpc_channel_credentials *result = NULL;
-  grpc_call_credentials *call_creds = NULL;
-
-  GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
-
-  gpr_once_init(&g_once, init_default_credentials);
-
-  gpr_mu_lock(&g_state_mu);
-
-  if (default_credentials != NULL) {
-    result = grpc_channel_credentials_ref(default_credentials);
-    goto end;
-  }
-
-  /* First, try the environment variable. */
-  call_creds = create_default_creds_from_path(
-      gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
-  if (call_creds != NULL) goto end;
-
-  /* Then the well-known file. */
-  call_creds = create_default_creds_from_path(
-      grpc_get_well_known_google_credentials_file_path());
-  if (call_creds != NULL) goto end;
-
-  /* At last try to see if we're on compute engine (do the detection only once
-     since it requires a network test). */
-  if (!compute_engine_detection_done) {
-    int need_compute_engine_creds = is_stack_running_on_compute_engine();
-    compute_engine_detection_done = 1;
-    if (need_compute_engine_creds) {
-      call_creds = grpc_google_compute_engine_credentials_create(NULL);
-    }
-  }
-
-end:
-  if (result == NULL) {
-    if (call_creds != NULL) {
-      /* Blend with default ssl credentials and add a global reference so that
-         it
-         can be cached and re-served. */
-      grpc_channel_credentials *ssl_creds =
-          grpc_ssl_credentials_create(NULL, NULL, NULL);
-      default_credentials = grpc_channel_credentials_ref(
-          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
-                                                    NULL));
-      GPR_ASSERT(default_credentials != NULL);
-      grpc_channel_credentials_unref(ssl_creds);
-      grpc_call_credentials_unref(call_creds);
-      result = default_credentials;
-    } else {
-      gpr_log(GPR_ERROR, "Could not create google default credentials.");
-    }
-  }
-  gpr_mu_unlock(&g_state_mu);
-  return result;
-}
-
-void grpc_flush_cached_google_default_credentials(void) {
-  gpr_once_init(&g_once, init_default_credentials);
-  gpr_mu_lock(&g_state_mu);
-  if (default_credentials != NULL) {
-    grpc_channel_credentials_unref(default_credentials);
-    default_credentials = NULL;
-  }
-  compute_engine_detection_done = 0;
-  gpr_mu_unlock(&g_state_mu);
-}
-
-/* -- Well known credentials path. -- */
-
-static grpc_well_known_credentials_path_getter creds_path_getter = NULL;
-
-char *grpc_get_well_known_google_credentials_file_path(void) {
-  if (creds_path_getter != NULL) return creds_path_getter();
-  return grpc_get_well_known_google_credentials_file_path_impl();
-}
-
-void grpc_override_well_known_credentials_path_getter(
-    grpc_well_known_credentials_path_getter getter) {
-  creds_path_getter = getter;
-}
diff --git a/src/core/lib/security/handshake.c b/src/core/lib/security/handshake.c
deleted file mode 100644
index d5fe0c7..0000000
--- a/src/core/lib/security/handshake.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/handshake.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include "src/core/lib/security/secure_endpoint.h"
-#include "src/core/lib/security/security_context.h"
-
-#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
-
-typedef struct {
-  grpc_security_connector *connector;
-  tsi_handshaker *handshaker;
-  bool is_client_side;
-  unsigned char *handshake_buffer;
-  size_t handshake_buffer_size;
-  grpc_endpoint *wrapped_endpoint;
-  grpc_endpoint *secure_endpoint;
-  gpr_slice_buffer left_overs;
-  gpr_slice_buffer incoming;
-  gpr_slice_buffer outgoing;
-  grpc_security_handshake_done_cb cb;
-  void *user_data;
-  grpc_closure on_handshake_data_sent_to_peer;
-  grpc_closure on_handshake_data_received_from_peer;
-  grpc_auth_context *auth_context;
-} grpc_security_handshake;
-
-static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
-                                                 void *setup, bool success);
-
-static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
-                                           bool success);
-
-static void security_connector_remove_handshake(grpc_security_handshake *h) {
-  GPR_ASSERT(!h->is_client_side);
-  grpc_security_connector_handshake_list *node;
-  grpc_security_connector_handshake_list *tmp;
-  grpc_server_security_connector *sc =
-      (grpc_server_security_connector *)h->connector;
-  gpr_mu_lock(&sc->mu);
-  node = sc->handshaking_handshakes;
-  if (node && node->handshake == h) {
-    sc->handshaking_handshakes = node->next;
-    gpr_free(node);
-    gpr_mu_unlock(&sc->mu);
-    return;
-  }
-  while (node) {
-    if (node->next->handshake == h) {
-      tmp = node->next;
-      node->next = node->next->next;
-      gpr_free(tmp);
-      gpr_mu_unlock(&sc->mu);
-      return;
-    }
-    node = node->next;
-  }
-  gpr_mu_unlock(&sc->mu);
-}
-
-static void security_handshake_done(grpc_exec_ctx *exec_ctx,
-                                    grpc_security_handshake *h,
-                                    int is_success) {
-  if (!h->is_client_side) {
-    security_connector_remove_handshake(h);
-  }
-  if (is_success) {
-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
-          h->auth_context);
-  } else {
-    if (h->secure_endpoint != NULL) {
-      grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
-      grpc_endpoint_destroy(exec_ctx, h->secure_endpoint);
-    } else {
-      grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
-    }
-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
-  }
-  if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
-  if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
-  gpr_slice_buffer_destroy(&h->left_overs);
-  gpr_slice_buffer_destroy(&h->outgoing);
-  gpr_slice_buffer_destroy(&h->incoming);
-  GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
-  GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
-  gpr_free(h);
-}
-
-static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
-                            grpc_security_status status,
-                            grpc_auth_context *auth_context) {
-  grpc_security_handshake *h = user_data;
-  tsi_frame_protector *protector;
-  tsi_result result;
-  if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR, "Error checking peer.");
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-  h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
-  result =
-      tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-  h->secure_endpoint =
-      grpc_secure_endpoint_create(protector, h->wrapped_endpoint,
-                                  h->left_overs.slices, h->left_overs.count);
-  h->left_overs.count = 0;
-  h->left_overs.length = 0;
-  security_handshake_done(exec_ctx, h, 1);
-  return;
-}
-
-static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
-  tsi_peer peer;
-  tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
-
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Peer extraction failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-  grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
-                                     on_peer_checked, h);
-}
-
-static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,
-                                         grpc_security_handshake *h) {
-  size_t offset = 0;
-  tsi_result result = TSI_OK;
-  gpr_slice to_send;
-
-  do {
-    size_t to_send_size = h->handshake_buffer_size - offset;
-    result = tsi_handshaker_get_bytes_to_send_to_peer(
-        h->handshaker, h->handshake_buffer + offset, &to_send_size);
-    offset += to_send_size;
-    if (result == TSI_INCOMPLETE_DATA) {
-      h->handshake_buffer_size *= 2;
-      h->handshake_buffer =
-          gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
-    }
-  } while (result == TSI_INCOMPLETE_DATA);
-
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshake failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-
-  to_send =
-      gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
-  gpr_slice_buffer_reset_and_unref(&h->outgoing);
-  gpr_slice_buffer_add(&h->outgoing, to_send);
-  /* TODO(klempner,jboeuf): This should probably use the client setup
-     deadline */
-  grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing,
-                      &h->on_handshake_data_sent_to_peer);
-}
-
-static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
-                                                 void *handshake,
-                                                 bool success) {
-  grpc_security_handshake *h = handshake;
-  size_t consumed_slice_size = 0;
-  tsi_result result = TSI_OK;
-  size_t i;
-  size_t num_left_overs;
-  int has_left_overs_in_current_slice = 0;
-
-  if (!success) {
-    gpr_log(GPR_ERROR, "Read failed.");
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-
-  for (i = 0; i < h->incoming.count; i++) {
-    consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
-    result = tsi_handshaker_process_bytes_from_peer(
-        h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
-        &consumed_slice_size);
-    if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
-  }
-
-  if (tsi_handshaker_is_in_progress(h->handshaker)) {
-    /* We may need more data. */
-    if (result == TSI_INCOMPLETE_DATA) {
-      grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
-                         &h->on_handshake_data_received_from_peer);
-      return;
-    } else {
-      send_handshake_bytes_to_peer(exec_ctx, h);
-      return;
-    }
-  }
-
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshake failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-
-  /* Handshake is done and successful this point. */
-  has_left_overs_in_current_slice =
-      (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
-  num_left_overs =
-      (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
-  if (num_left_overs == 0) {
-    check_peer(exec_ctx, h);
-    return;
-  }
-
-  /* Put the leftovers in our buffer (ownership transfered). */
-  if (has_left_overs_in_current_slice) {
-    gpr_slice_buffer_add(
-        &h->left_overs,
-        gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
-    gpr_slice_unref(
-        h->incoming.slices[i]); /* split_tail above increments refcount. */
-  }
-  gpr_slice_buffer_addn(
-      &h->left_overs, &h->incoming.slices[i + 1],
-      num_left_overs - (size_t)has_left_overs_in_current_slice);
-  check_peer(exec_ctx, h);
-}
-
-/* If handshake is NULL, the handshake is done. */
-static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
-                                           void *handshake, bool success) {
-  grpc_security_handshake *h = handshake;
-
-  /* Make sure that write is OK. */
-  if (!success) {
-    gpr_log(GPR_ERROR, "Write failed.");
-    if (handshake != NULL) security_handshake_done(exec_ctx, h, 0);
-    return;
-  }
-
-  /* We may be done. */
-  if (tsi_handshaker_is_in_progress(h->handshaker)) {
-    /* TODO(klempner,jboeuf): This should probably use the client setup
-       deadline */
-    grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
-                       &h->on_handshake_data_received_from_peer);
-  } else {
-    check_peer(exec_ctx, h);
-  }
-}
-
-void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
-                                tsi_handshaker *handshaker,
-                                grpc_security_connector *connector,
-                                bool is_client_side,
-                                grpc_endpoint *nonsecure_endpoint,
-                                grpc_security_handshake_done_cb cb,
-                                void *user_data) {
-  grpc_security_connector_handshake_list *handshake_node;
-  grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
-  memset(h, 0, sizeof(grpc_security_handshake));
-  h->handshaker = handshaker;
-  h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
-  h->is_client_side = is_client_side;
-  h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
-  h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
-  h->wrapped_endpoint = nonsecure_endpoint;
-  h->user_data = user_data;
-  h->cb = cb;
-  grpc_closure_init(&h->on_handshake_data_sent_to_peer,
-                    on_handshake_data_sent_to_peer, h);
-  grpc_closure_init(&h->on_handshake_data_received_from_peer,
-                    on_handshake_data_received_from_peer, h);
-  gpr_slice_buffer_init(&h->left_overs);
-  gpr_slice_buffer_init(&h->outgoing);
-  gpr_slice_buffer_init(&h->incoming);
-  if (!is_client_side) {
-    grpc_server_security_connector *server_connector =
-        (grpc_server_security_connector *)connector;
-    handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
-    handshake_node->handshake = h;
-    gpr_mu_lock(&server_connector->mu);
-    handshake_node->next = server_connector->handshaking_handshakes;
-    server_connector->handshaking_handshakes = handshake_node;
-    gpr_mu_unlock(&server_connector->mu);
-  }
-  send_handshake_bytes_to_peer(exec_ctx, h);
-}
-
-void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
-                                      void *handshake) {
-  grpc_security_handshake *h = handshake;
-  grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
-}
diff --git a/src/core/lib/security/handshake.h b/src/core/lib/security/handshake.h
deleted file mode 100644
index f34476e..0000000
--- a/src/core/lib/security/handshake.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_HANDSHAKE_H
-#define GRPC_CORE_LIB_SECURITY_HANDSHAKE_H
-
-#include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/security/security_connector.h"
-
-/* Calls the callback upon completion. Takes owership of handshaker. */
-void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
-                                tsi_handshaker *handshaker,
-                                grpc_security_connector *connector,
-                                bool is_client_side,
-                                grpc_endpoint *nonsecure_endpoint,
-                                grpc_security_handshake_done_cb cb,
-                                void *user_data);
-
-void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
-
-#endif /* GRPC_CORE_LIB_SECURITY_HANDSHAKE_H */
diff --git a/src/core/lib/security/json_token.c b/src/core/lib/security/json_token.c
deleted file mode 100644
index d5bc2c8..0000000
--- a/src/core/lib/security/json_token.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/json_token.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/security/b64.h"
-#include "src/core/lib/support/string.h"
-
-#include <openssl/bio.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-/* --- Constants. --- */
-
-/* 1 hour max. */
-gpr_timespec grpc_max_auth_token_lifetime() {
-  gpr_timespec out;
-  out.tv_sec = 3600;
-  out.tv_nsec = 0;
-  out.clock_type = GPR_TIMESPAN;
-  return out;
-}
-
-#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
-#define GRPC_JWT_TYPE "JWT"
-
-/* --- Override for testing. --- */
-
-static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL;
-
-/* --- grpc_auth_json_key. --- */
-
-static const char *json_get_string_property(const grpc_json *json,
-                                            const char *prop_name) {
-  grpc_json *child;
-  for (child = json->child; child != NULL; child = child->next) {
-    if (strcmp(child->key, prop_name) == 0) break;
-  }
-  if (child == NULL || child->type != GRPC_JSON_STRING) {
-    gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name);
-    return NULL;
-  }
-  return child->value;
-}
-
-static int set_json_key_string_property(const grpc_json *json,
-                                        const char *prop_name,
-                                        char **json_key_field) {
-  const char *prop_value = json_get_string_property(json, prop_name);
-  if (prop_value == NULL) return 0;
-  *json_key_field = gpr_strdup(prop_value);
-  return 1;
-}
-
-int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) {
-  return (json_key != NULL) &&
-         strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
-}
-
-grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) {
-  grpc_auth_json_key result;
-  BIO *bio = NULL;
-  const char *prop_value;
-  int success = 0;
-
-  memset(&result, 0, sizeof(grpc_auth_json_key));
-  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
-  if (json == NULL) {
-    gpr_log(GPR_ERROR, "Invalid json.");
-    goto end;
-  }
-
-  prop_value = json_get_string_property(json, "type");
-  if (prop_value == NULL ||
-      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) {
-    goto end;
-  }
-  result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT;
-
-  if (!set_json_key_string_property(json, "private_key_id",
-                                    &result.private_key_id) ||
-      !set_json_key_string_property(json, "client_id", &result.client_id) ||
-      !set_json_key_string_property(json, "client_email",
-                                    &result.client_email)) {
-    goto end;
-  }
-
-  prop_value = json_get_string_property(json, "private_key");
-  if (prop_value == NULL) {
-    goto end;
-  }
-  bio = BIO_new(BIO_s_mem());
-  success = BIO_puts(bio, prop_value);
-  if ((success < 0) || ((size_t)success != strlen(prop_value))) {
-    gpr_log(GPR_ERROR, "Could not write into openssl BIO.");
-    goto end;
-  }
-  result.private_key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, "");
-  if (result.private_key == NULL) {
-    gpr_log(GPR_ERROR, "Could not deserialize private key.");
-    goto end;
-  }
-  success = 1;
-
-end:
-  if (bio != NULL) BIO_free(bio);
-  if (!success) grpc_auth_json_key_destruct(&result);
-  return result;
-}
-
-grpc_auth_json_key grpc_auth_json_key_create_from_string(
-    const char *json_string) {
-  char *scratchpad = gpr_strdup(json_string);
-  grpc_json *json = grpc_json_parse_string(scratchpad);
-  grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json);
-  if (json != NULL) grpc_json_destroy(json);
-  gpr_free(scratchpad);
-  return result;
-}
-
-void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) {
-  if (json_key == NULL) return;
-  json_key->type = GRPC_AUTH_JSON_TYPE_INVALID;
-  if (json_key->client_id != NULL) {
-    gpr_free(json_key->client_id);
-    json_key->client_id = NULL;
-  }
-  if (json_key->private_key_id != NULL) {
-    gpr_free(json_key->private_key_id);
-    json_key->private_key_id = NULL;
-  }
-  if (json_key->client_email != NULL) {
-    gpr_free(json_key->client_email);
-    json_key->client_email = NULL;
-  }
-  if (json_key->private_key != NULL) {
-    RSA_free(json_key->private_key);
-    json_key->private_key = NULL;
-  }
-}
-
-/* --- jwt encoding and signature. --- */
-
-static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
-                               const char *key, const char *value,
-                               grpc_json_type type) {
-  grpc_json *child = grpc_json_create(type);
-  if (brother) brother->next = child;
-  if (!parent->child) parent->child = child;
-  child->parent = parent;
-  child->value = value;
-  child->key = key;
-  return child;
-}
-
-static char *encoded_jwt_header(const char *key_id, const char *algorithm) {
-  grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
-  grpc_json *child = NULL;
-  char *json_str = NULL;
-  char *result = NULL;
-
-  child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING);
-  child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
-  create_child(child, json, "kid", key_id, GRPC_JSON_STRING);
-
-  json_str = grpc_json_dump_to_string(json, 0);
-  result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
-  gpr_free(json_str);
-  grpc_json_destroy(json);
-  return result;
-}
-
-static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
-                               const char *audience,
-                               gpr_timespec token_lifetime, const char *scope) {
-  grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
-  grpc_json *child = NULL;
-  char *json_str = NULL;
-  char *result = NULL;
-  gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
-  gpr_timespec expiration = gpr_time_add(now, token_lifetime);
-  char now_str[GPR_LTOA_MIN_BUFSIZE];
-  char expiration_str[GPR_LTOA_MIN_BUFSIZE];
-  if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) {
-    gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value.");
-    expiration = gpr_time_add(now, grpc_max_auth_token_lifetime());
-  }
-  int64_ttoa(now.tv_sec, now_str);
-  int64_ttoa(expiration.tv_sec, expiration_str);
-
-  child =
-      create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING);
-  if (scope != NULL) {
-    child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
-  } else {
-    /* Unscoped JWTs need a sub field. */
-    child = create_child(child, json, "sub", json_key->client_email,
-                         GRPC_JSON_STRING);
-  }
-
-  child = create_child(child, json, "aud", audience, GRPC_JSON_STRING);
-  child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER);
-  create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER);
-
-  json_str = grpc_json_dump_to_string(json, 0);
-  result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
-  gpr_free(json_str);
-  grpc_json_destroy(json);
-  return result;
-}
-
-static char *dot_concat_and_free_strings(char *str1, char *str2) {
-  size_t str1_len = strlen(str1);
-  size_t str2_len = strlen(str2);
-  size_t result_len = str1_len + 1 /* dot */ + str2_len;
-  char *result = gpr_malloc(result_len + 1 /* NULL terminated */);
-  char *current = result;
-  memcpy(current, str1, str1_len);
-  current += str1_len;
-  *(current++) = '.';
-  memcpy(current, str2, str2_len);
-  current += str2_len;
-  GPR_ASSERT(current >= result);
-  GPR_ASSERT((uintptr_t)(current - result) == result_len);
-  *current = '\0';
-  gpr_free(str1);
-  gpr_free(str2);
-  return result;
-}
-
-const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) {
-  if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) {
-    return EVP_sha256();
-  } else {
-    gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm);
-    return NULL;
-  }
-}
-
-char *compute_and_encode_signature(const grpc_auth_json_key *json_key,
-                                   const char *signature_algorithm,
-                                   const char *to_sign) {
-  const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm);
-  EVP_MD_CTX *md_ctx = NULL;
-  EVP_PKEY *key = EVP_PKEY_new();
-  size_t sig_len = 0;
-  unsigned char *sig = NULL;
-  char *result = NULL;
-  if (md == NULL) return NULL;
-  md_ctx = EVP_MD_CTX_create();
-  if (md_ctx == NULL) {
-    gpr_log(GPR_ERROR, "Could not create MD_CTX");
-    goto end;
-  }
-  EVP_PKEY_set1_RSA(key, json_key->private_key);
-  if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) {
-    gpr_log(GPR_ERROR, "DigestInit failed.");
-    goto end;
-  }
-  if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) {
-    gpr_log(GPR_ERROR, "DigestUpdate failed.");
-    goto end;
-  }
-  if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
-    gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed.");
-    goto end;
-  }
-  sig = gpr_malloc(sig_len);
-  if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
-    gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
-    goto end;
-  }
-  result = grpc_base64_encode(sig, sig_len, 1, 0);
-
-end:
-  if (key != NULL) EVP_PKEY_free(key);
-  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
-  if (sig != NULL) gpr_free(sig);
-  return result;
-}
-
-char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
-                               const char *audience,
-                               gpr_timespec token_lifetime, const char *scope) {
-  if (g_jwt_encode_and_sign_override != NULL) {
-    return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime,
-                                          scope);
-  } else {
-    const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM;
-    char *to_sign = dot_concat_and_free_strings(
-        encoded_jwt_header(json_key->private_key_id, sig_algo),
-        encoded_jwt_claim(json_key, audience, token_lifetime, scope));
-    char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign);
-    if (sig == NULL) {
-      gpr_free(to_sign);
-      return NULL;
-    }
-    return dot_concat_and_free_strings(to_sign, sig);
-  }
-}
-
-void grpc_jwt_encode_and_sign_set_override(
-    grpc_jwt_encode_and_sign_override func) {
-  g_jwt_encode_and_sign_override = func;
-}
-
-/* --- grpc_auth_refresh_token --- */
-
-int grpc_auth_refresh_token_is_valid(
-    const grpc_auth_refresh_token *refresh_token) {
-  return (refresh_token != NULL) &&
-         strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
-}
-
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
-    const grpc_json *json) {
-  grpc_auth_refresh_token result;
-  const char *prop_value;
-  int success = 0;
-
-  memset(&result, 0, sizeof(grpc_auth_refresh_token));
-  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
-  if (json == NULL) {
-    gpr_log(GPR_ERROR, "Invalid json.");
-    goto end;
-  }
-
-  prop_value = json_get_string_property(json, "type");
-  if (prop_value == NULL ||
-      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) {
-    goto end;
-  }
-  result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER;
-
-  if (!set_json_key_string_property(json, "client_secret",
-                                    &result.client_secret) ||
-      !set_json_key_string_property(json, "client_id", &result.client_id) ||
-      !set_json_key_string_property(json, "refresh_token",
-                                    &result.refresh_token)) {
-    goto end;
-  }
-  success = 1;
-
-end:
-  if (!success) grpc_auth_refresh_token_destruct(&result);
-  return result;
-}
-
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
-    const char *json_string) {
-  char *scratchpad = gpr_strdup(json_string);
-  grpc_json *json = grpc_json_parse_string(scratchpad);
-  grpc_auth_refresh_token result =
-      grpc_auth_refresh_token_create_from_json(json);
-  if (json != NULL) grpc_json_destroy(json);
-  gpr_free(scratchpad);
-  return result;
-}
-
-void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
-  if (refresh_token == NULL) return;
-  refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID;
-  if (refresh_token->client_id != NULL) {
-    gpr_free(refresh_token->client_id);
-    refresh_token->client_id = NULL;
-  }
-  if (refresh_token->client_secret != NULL) {
-    gpr_free(refresh_token->client_secret);
-    refresh_token->client_secret = NULL;
-  }
-  if (refresh_token->refresh_token != NULL) {
-    gpr_free(refresh_token->refresh_token);
-    refresh_token->refresh_token = NULL;
-  }
-}
diff --git a/src/core/lib/security/json_token.h b/src/core/lib/security/json_token.h
deleted file mode 100644
index 123fa65..0000000
--- a/src/core/lib/security/json_token.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_JSON_TOKEN_H
-#define GRPC_CORE_LIB_SECURITY_JSON_TOKEN_H
-
-#include <grpc/support/slice.h>
-#include <openssl/rsa.h>
-
-#include "src/core/lib/json/json.h"
-
-/* --- Constants. --- */
-
-#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
-
-#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
-#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
-#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
-
-/* --- auth_json_key parsing. --- */
-
-typedef struct {
-  const char *type;
-  char *private_key_id;
-  char *client_id;
-  char *client_email;
-  RSA *private_key;
-} grpc_auth_json_key;
-
-/* Returns 1 if the object is valid, 0 otherwise. */
-int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key);
-
-/* Creates a json_key object from string. Returns an invalid object if a parsing
-   error has been encountered. */
-grpc_auth_json_key grpc_auth_json_key_create_from_string(
-    const char *json_string);
-
-/* Creates a json_key object from parsed json. Returns an invalid object if a
-   parsing error has been encountered. */
-grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
-
-/* Destructs the object. */
-void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
-
-/* --- json token encoding and signing. --- */
-
-/* Caller is responsible for calling gpr_free on the returned value. May return
-   NULL on invalid input. The scope parameter may be NULL. */
-char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
-                               const char *audience,
-                               gpr_timespec token_lifetime, const char *scope);
-
-/* Override encode_and_sign function for testing. */
-typedef char *(*grpc_jwt_encode_and_sign_override)(
-    const grpc_auth_json_key *json_key, const char *audience,
-    gpr_timespec token_lifetime, const char *scope);
-
-/* Set a custom encode_and_sign override for testing. */
-void grpc_jwt_encode_and_sign_set_override(
-    grpc_jwt_encode_and_sign_override func);
-
-/* --- auth_refresh_token parsing. --- */
-
-typedef struct {
-  const char *type;
-  char *client_id;
-  char *client_secret;
-  char *refresh_token;
-} grpc_auth_refresh_token;
-
-/* Returns 1 if the object is valid, 0 otherwise. */
-int grpc_auth_refresh_token_is_valid(
-    const grpc_auth_refresh_token *refresh_token);
-
-/* Creates a refresh token object from string. Returns an invalid object if a
-   parsing error has been encountered. */
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
-    const char *json_string);
-
-/* Creates a refresh token object from parsed json. Returns an invalid object if
-   a parsing error has been encountered. */
-grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
-    const grpc_json *json);
-
-/* Destructs the object. */
-void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
-
-#endif /* GRPC_CORE_LIB_SECURITY_JSON_TOKEN_H */
diff --git a/src/core/lib/security/jwt_verifier.c b/src/core/lib/security/jwt_verifier.c
deleted file mode 100644
index 1b6b7b1..0000000
--- a/src/core/lib/security/jwt_verifier.c
+++ /dev/null
@@ -1,846 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/jwt_verifier.h"
-
-#include <limits.h>
-#include <string.h>
-
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/iomgr/pops.h"
-#include "src/core/lib/security/b64.h"
-#include "src/core/lib/tsi/ssl_types.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <openssl/pem.h>
-
-/* --- Utils. --- */
-
-const char *grpc_jwt_verifier_status_to_string(
-    grpc_jwt_verifier_status status) {
-  switch (status) {
-    case GRPC_JWT_VERIFIER_OK:
-      return "OK";
-    case GRPC_JWT_VERIFIER_BAD_SIGNATURE:
-      return "BAD_SIGNATURE";
-    case GRPC_JWT_VERIFIER_BAD_FORMAT:
-      return "BAD_FORMAT";
-    case GRPC_JWT_VERIFIER_BAD_AUDIENCE:
-      return "BAD_AUDIENCE";
-    case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR:
-      return "KEY_RETRIEVAL_ERROR";
-    case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE:
-      return "TIME_CONSTRAINT_FAILURE";
-    case GRPC_JWT_VERIFIER_GENERIC_ERROR:
-      return "GENERIC_ERROR";
-    default:
-      return "UNKNOWN";
-  }
-}
-
-static const EVP_MD *evp_md_from_alg(const char *alg) {
-  if (strcmp(alg, "RS256") == 0) {
-    return EVP_sha256();
-  } else if (strcmp(alg, "RS384") == 0) {
-    return EVP_sha384();
-  } else if (strcmp(alg, "RS512") == 0) {
-    return EVP_sha512();
-  } else {
-    return NULL;
-  }
-}
-
-static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
-                                           gpr_slice *buffer) {
-  grpc_json *json;
-
-  *buffer = grpc_base64_decode_with_len(str, len, 1);
-  if (GPR_SLICE_IS_EMPTY(*buffer)) {
-    gpr_log(GPR_ERROR, "Invalid base64.");
-    return NULL;
-  }
-  json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer),
-                                         GPR_SLICE_LENGTH(*buffer));
-  if (json == NULL) {
-    gpr_slice_unref(*buffer);
-    gpr_log(GPR_ERROR, "JSON parsing error.");
-  }
-  return json;
-}
-
-static const char *validate_string_field(const grpc_json *json,
-                                         const char *key) {
-  if (json->type != GRPC_JSON_STRING) {
-    gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
-    return NULL;
-  }
-  return json->value;
-}
-
-static gpr_timespec validate_time_field(const grpc_json *json,
-                                        const char *key) {
-  gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME);
-  if (json->type != GRPC_JSON_NUMBER) {
-    gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
-    return result;
-  }
-  result.tv_sec = strtol(json->value, NULL, 10);
-  return result;
-}
-
-/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
-
-typedef struct {
-  const char *alg;
-  const char *kid;
-  const char *typ;
-  /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
-  gpr_slice buffer;
-} jose_header;
-
-static void jose_header_destroy(jose_header *h) {
-  gpr_slice_unref(h->buffer);
-  gpr_free(h);
-}
-
-/* Takes ownership of json and buffer. */
-static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) {
-  grpc_json *cur;
-  jose_header *h = gpr_malloc(sizeof(jose_header));
-  memset(h, 0, sizeof(jose_header));
-  h->buffer = buffer;
-  for (cur = json->child; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->key, "alg") == 0) {
-      /* We only support RSA-1.5 signatures for now.
-         Beware of this if we add HMAC support:
-         https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
-       */
-      if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) ||
-          evp_md_from_alg(cur->value) == NULL) {
-        gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value);
-        goto error;
-      }
-      h->alg = cur->value;
-    } else if (strcmp(cur->key, "typ") == 0) {
-      h->typ = validate_string_field(cur, "typ");
-      if (h->typ == NULL) goto error;
-    } else if (strcmp(cur->key, "kid") == 0) {
-      h->kid = validate_string_field(cur, "kid");
-      if (h->kid == NULL) goto error;
-    }
-  }
-  if (h->alg == NULL) {
-    gpr_log(GPR_ERROR, "Missing alg field.");
-    goto error;
-  }
-  grpc_json_destroy(json);
-  h->buffer = buffer;
-  return h;
-
-error:
-  grpc_json_destroy(json);
-  jose_header_destroy(h);
-  return NULL;
-}
-
-/* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */
-
-struct grpc_jwt_claims {
-  /* Well known properties already parsed. */
-  const char *sub;
-  const char *iss;
-  const char *aud;
-  const char *jti;
-  gpr_timespec iat;
-  gpr_timespec exp;
-  gpr_timespec nbf;
-
-  grpc_json *json;
-  gpr_slice buffer;
-};
-
-void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
-  grpc_json_destroy(claims->json);
-  gpr_slice_unref(claims->buffer);
-  gpr_free(claims);
-}
-
-const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return NULL;
-  return claims->json;
-}
-
-const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return NULL;
-  return claims->sub;
-}
-
-const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return NULL;
-  return claims->iss;
-}
-
-const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return NULL;
-  return claims->jti;
-}
-
-const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return NULL;
-  return claims->aud;
-}
-
-gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
-  return claims->iat;
-}
-
-gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME);
-  return claims->exp;
-}
-
-gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
-  return claims->nbf;
-}
-
-/* Takes ownership of json and buffer even in case of failure. */
-grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) {
-  grpc_json *cur;
-  grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims));
-  memset(claims, 0, sizeof(grpc_jwt_claims));
-  claims->json = json;
-  claims->buffer = buffer;
-  claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME);
-  claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME);
-  claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME);
-
-  /* Per the spec, all fields are optional. */
-  for (cur = json->child; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->key, "sub") == 0) {
-      claims->sub = validate_string_field(cur, "sub");
-      if (claims->sub == NULL) goto error;
-    } else if (strcmp(cur->key, "iss") == 0) {
-      claims->iss = validate_string_field(cur, "iss");
-      if (claims->iss == NULL) goto error;
-    } else if (strcmp(cur->key, "aud") == 0) {
-      claims->aud = validate_string_field(cur, "aud");
-      if (claims->aud == NULL) goto error;
-    } else if (strcmp(cur->key, "jti") == 0) {
-      claims->jti = validate_string_field(cur, "jti");
-      if (claims->jti == NULL) goto error;
-    } else if (strcmp(cur->key, "iat") == 0) {
-      claims->iat = validate_time_field(cur, "iat");
-      if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
-        goto error;
-    } else if (strcmp(cur->key, "exp") == 0) {
-      claims->exp = validate_time_field(cur, "exp");
-      if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
-        goto error;
-    } else if (strcmp(cur->key, "nbf") == 0) {
-      claims->nbf = validate_time_field(cur, "nbf");
-      if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
-        goto error;
-    }
-  }
-  return claims;
-
-error:
-  grpc_jwt_claims_destroy(claims);
-  return NULL;
-}
-
-grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
-                                               const char *audience) {
-  gpr_timespec skewed_now;
-  int audience_ok;
-
-  GPR_ASSERT(claims != NULL);
-
-  skewed_now =
-      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
-  if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
-    gpr_log(GPR_ERROR, "JWT is not valid yet.");
-    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
-  }
-  skewed_now =
-      gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
-  if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
-    gpr_log(GPR_ERROR, "JWT is expired.");
-    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
-  }
-
-  if (audience == NULL) {
-    audience_ok = claims->aud == NULL;
-  } else {
-    audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0;
-  }
-  if (!audience_ok) {
-    gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.",
-            audience == NULL ? "NULL" : audience,
-            claims->aud == NULL ? "NULL" : claims->aud);
-    return GRPC_JWT_VERIFIER_BAD_AUDIENCE;
-  }
-  return GRPC_JWT_VERIFIER_OK;
-}
-
-/* --- verifier_cb_ctx object. --- */
-
-typedef struct {
-  grpc_jwt_verifier *verifier;
-  grpc_pops pops;
-  jose_header *header;
-  grpc_jwt_claims *claims;
-  char *audience;
-  gpr_slice signature;
-  gpr_slice signed_data;
-  void *user_data;
-  grpc_jwt_verification_done_cb user_cb;
-} verifier_cb_ctx;
-
-/* Takes ownership of the header, claims and signature. */
-static verifier_cb_ctx *verifier_cb_ctx_create(
-    grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header,
-    grpc_jwt_claims *claims, const char *audience, gpr_slice signature,
-    const char *signed_jwt, size_t signed_jwt_len, void *user_data,
-    grpc_jwt_verification_done_cb cb) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
-  memset(ctx, 0, sizeof(verifier_cb_ctx));
-  ctx->verifier = verifier;
-  ctx->pops = grpc_pops_create_from_pollset(pollset);
-  ctx->header = header;
-  ctx->audience = gpr_strdup(audience);
-  ctx->claims = claims;
-  ctx->signature = signature;
-  ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len);
-  ctx->user_data = user_data;
-  ctx->user_cb = cb;
-  grpc_exec_ctx_finish(&exec_ctx);
-  return ctx;
-}
-
-void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
-  if (ctx->audience != NULL) gpr_free(ctx->audience);
-  if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims);
-  gpr_slice_unref(ctx->signature);
-  gpr_slice_unref(ctx->signed_data);
-  jose_header_destroy(ctx->header);
-  /* TODO: see what to do with claims... */
-  gpr_free(ctx);
-}
-
-/* --- grpc_jwt_verifier object. --- */
-
-/* Clock skew defaults to one minute. */
-gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
-
-/* Max delay defaults to one minute. */
-gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN};
-
-typedef struct {
-  char *email_domain;
-  char *key_url_prefix;
-} email_key_mapping;
-
-struct grpc_jwt_verifier {
-  email_key_mapping *mappings;
-  size_t num_mappings; /* Should be very few, linear search ok. */
-  size_t allocated_mappings;
-  grpc_httpcli_context http_ctx;
-};
-
-static grpc_json *json_from_http(const grpc_httpcli_response *response) {
-  grpc_json *json = NULL;
-
-  if (response == NULL) {
-    gpr_log(GPR_ERROR, "HTTP response is NULL.");
-    return NULL;
-  }
-  if (response->status != 200) {
-    gpr_log(GPR_ERROR, "Call to http server failed with error %d.",
-            response->status);
-    return NULL;
-  }
-
-  json = grpc_json_parse_string_with_len(response->body, response->body_length);
-  if (json == NULL) {
-    gpr_log(GPR_ERROR, "Invalid JSON found in response.");
-  }
-  return json;
-}
-
-static const grpc_json *find_property_by_name(const grpc_json *json,
-                                              const char *name) {
-  const grpc_json *cur;
-  for (cur = json->child; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->key, name) == 0) return cur;
-  }
-  return NULL;
-}
-
-static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
-  X509 *x509 = NULL;
-  EVP_PKEY *result = NULL;
-  BIO *bio = BIO_new(BIO_s_mem());
-  size_t len = strlen(x509_str);
-  GPR_ASSERT(len < INT_MAX);
-  BIO_write(bio, x509_str, (int)len);
-  x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
-  if (x509 == NULL) {
-    gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
-    goto end;
-  }
-  result = X509_get_pubkey(x509);
-  if (result == NULL) {
-    gpr_log(GPR_ERROR, "Cannot find public key in X509 cert.");
-  }
-
-end:
-  BIO_free(bio);
-  if (x509 != NULL) X509_free(x509);
-  return result;
-}
-
-static BIGNUM *bignum_from_base64(const char *b64) {
-  BIGNUM *result = NULL;
-  gpr_slice bin;
-
-  if (b64 == NULL) return NULL;
-  bin = grpc_base64_decode(b64, 1);
-  if (GPR_SLICE_IS_EMPTY(bin)) {
-    gpr_log(GPR_ERROR, "Invalid base64 for big num.");
-    return NULL;
-  }
-  result = BN_bin2bn(GPR_SLICE_START_PTR(bin),
-                     TSI_SIZE_AS_SIZE(GPR_SLICE_LENGTH(bin)), NULL);
-  gpr_slice_unref(bin);
-  return result;
-}
-
-static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
-  const grpc_json *key_prop;
-  RSA *rsa = NULL;
-  EVP_PKEY *result = NULL;
-
-  GPR_ASSERT(kty != NULL && json != NULL);
-  if (strcmp(kty, "RSA") != 0) {
-    gpr_log(GPR_ERROR, "Unsupported key type %s.", kty);
-    goto end;
-  }
-  rsa = RSA_new();
-  if (rsa == NULL) {
-    gpr_log(GPR_ERROR, "Could not create rsa key.");
-    goto end;
-  }
-  for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
-    if (strcmp(key_prop->key, "n") == 0) {
-      rsa->n = bignum_from_base64(validate_string_field(key_prop, "n"));
-      if (rsa->n == NULL) goto end;
-    } else if (strcmp(key_prop->key, "e") == 0) {
-      rsa->e = bignum_from_base64(validate_string_field(key_prop, "e"));
-      if (rsa->e == NULL) goto end;
-    }
-  }
-  if (rsa->e == NULL || rsa->n == NULL) {
-    gpr_log(GPR_ERROR, "Missing RSA public key field.");
-    goto end;
-  }
-  result = EVP_PKEY_new();
-  EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
-
-end:
-  if (rsa != NULL) RSA_free(rsa);
-  return result;
-}
-
-static EVP_PKEY *find_verification_key(const grpc_json *json,
-                                       const char *header_alg,
-                                       const char *header_kid) {
-  const grpc_json *jkey;
-  const grpc_json *jwk_keys;
-  /* Try to parse the json as a JWK set:
-     https://tools.ietf.org/html/rfc7517#section-5. */
-  jwk_keys = find_property_by_name(json, "keys");
-  if (jwk_keys == NULL) {
-    /* Use the google proprietary format which is:
-       { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
-    const grpc_json *cur = find_property_by_name(json, header_kid);
-    if (cur == NULL) return NULL;
-    return extract_pkey_from_x509(cur->value);
-  }
-
-  if (jwk_keys->type != GRPC_JSON_ARRAY) {
-    gpr_log(GPR_ERROR,
-            "Unexpected value type of keys property in jwks key set.");
-    return NULL;
-  }
-  /* Key format is specified in:
-     https://tools.ietf.org/html/rfc7518#section-6. */
-  for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) {
-    grpc_json *key_prop;
-    const char *alg = NULL;
-    const char *kid = NULL;
-    const char *kty = NULL;
-
-    if (jkey->type != GRPC_JSON_OBJECT) continue;
-    for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) {
-      if (strcmp(key_prop->key, "alg") == 0 &&
-          key_prop->type == GRPC_JSON_STRING) {
-        alg = key_prop->value;
-      } else if (strcmp(key_prop->key, "kid") == 0 &&
-                 key_prop->type == GRPC_JSON_STRING) {
-        kid = key_prop->value;
-      } else if (strcmp(key_prop->key, "kty") == 0 &&
-                 key_prop->type == GRPC_JSON_STRING) {
-        kty = key_prop->value;
-      }
-    }
-    if (alg != NULL && kid != NULL && kty != NULL &&
-        strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
-      return pkey_from_jwk(jkey, kty);
-    }
-  }
-  gpr_log(GPR_ERROR,
-          "Could not find matching key in key set for kid=%s and alg=%s",
-          header_kid, header_alg);
-  return NULL;
-}
-
-static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
-                                gpr_slice signature, gpr_slice signed_data) {
-  EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
-  const EVP_MD *md = evp_md_from_alg(alg);
-  int result = 0;
-
-  GPR_ASSERT(md != NULL); /* Checked before. */
-  if (md_ctx == NULL) {
-    gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX.");
-    goto end;
-  }
-  if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) {
-    gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed.");
-    goto end;
-  }
-  if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data),
-                             GPR_SLICE_LENGTH(signed_data)) != 1) {
-    gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
-    goto end;
-  }
-  if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature),
-                            GPR_SLICE_LENGTH(signature)) != 1) {
-    gpr_log(GPR_ERROR, "JWT signature verification failed.");
-    goto end;
-  }
-  result = 1;
-
-end:
-  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
-  return result;
-}
-
-static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
-                              const grpc_httpcli_response *response) {
-  grpc_json *json = json_from_http(response);
-  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
-  EVP_PKEY *verification_key = NULL;
-  grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
-  grpc_jwt_claims *claims = NULL;
-
-  if (json == NULL) {
-    status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
-    goto end;
-  }
-  verification_key =
-      find_verification_key(json, ctx->header->alg, ctx->header->kid);
-  if (verification_key == NULL) {
-    gpr_log(GPR_ERROR, "Could not find verification key with kid %s.",
-            ctx->header->kid);
-    status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
-    goto end;
-  }
-
-  if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature,
-                            ctx->signed_data)) {
-    status = GRPC_JWT_VERIFIER_BAD_SIGNATURE;
-    goto end;
-  }
-
-  status = grpc_jwt_claims_check(ctx->claims, ctx->audience);
-  if (status == GRPC_JWT_VERIFIER_OK) {
-    /* Pass ownership. */
-    claims = ctx->claims;
-    ctx->claims = NULL;
-  }
-
-end:
-  if (json != NULL) grpc_json_destroy(json);
-  if (verification_key != NULL) EVP_PKEY_free(verification_key);
-  ctx->user_cb(ctx->user_data, status, claims);
-  verifier_cb_ctx_destroy(ctx);
-}
-
-static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       const grpc_httpcli_response *response) {
-  const grpc_json *cur;
-  grpc_json *json = json_from_http(response);
-  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
-  grpc_httpcli_request req;
-  const char *jwks_uri;
-
-  /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
-  if (json == NULL) goto error;
-  cur = find_property_by_name(json, "jwks_uri");
-  if (cur == NULL) {
-    gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
-    goto error;
-  }
-  jwks_uri = validate_string_field(cur, "jwks_uri");
-  if (jwks_uri == NULL) goto error;
-  if (strstr(jwks_uri, "https://") != jwks_uri) {
-    gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
-    goto error;
-  }
-  jwks_uri += 8;
-  req.handshaker = &grpc_httpcli_ssl;
-  req.host = gpr_strdup(jwks_uri);
-  req.http.path = strchr(jwks_uri, '/');
-  if (req.http.path == NULL) {
-    req.http.path = "";
-  } else {
-    *(req.host + (req.http.path - jwks_uri)) = '\0';
-  }
-  grpc_httpcli_get(
-      exec_ctx, &ctx->verifier->http_ctx, &ctx->pops, &req,
-      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
-      on_keys_retrieved, ctx);
-  grpc_json_destroy(json);
-  gpr_free(req.host);
-  return;
-
-error:
-  if (json != NULL) grpc_json_destroy(json);
-  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
-  verifier_cb_ctx_destroy(ctx);
-}
-
-static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
-                                               const char *email_domain) {
-  size_t i;
-  if (v->mappings == NULL) return NULL;
-  for (i = 0; i < v->num_mappings; i++) {
-    if (strcmp(email_domain, v->mappings[i].email_domain) == 0) {
-      return &v->mappings[i];
-    }
-  }
-  return NULL;
-}
-
-static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
-                                 const char *key_url_prefix) {
-  email_key_mapping *mapping = verifier_get_mapping(v, email_domain);
-  GPR_ASSERT(v->num_mappings < v->allocated_mappings);
-  if (mapping != NULL) {
-    gpr_free(mapping->key_url_prefix);
-    mapping->key_url_prefix = gpr_strdup(key_url_prefix);
-    return;
-  }
-  v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain);
-  v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix);
-  v->num_mappings++;
-  GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
-}
-
-/* Takes ownership of ctx. */
-static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
-                                    verifier_cb_ctx *ctx) {
-  const char *at_sign;
-  grpc_httpcli_response_cb http_cb;
-  char *path_prefix = NULL;
-  const char *iss;
-  grpc_httpcli_request req;
-  memset(&req, 0, sizeof(grpc_httpcli_request));
-  req.handshaker = &grpc_httpcli_ssl;
-
-  GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
-  iss = ctx->claims->iss;
-  if (ctx->header->kid == NULL) {
-    gpr_log(GPR_ERROR, "Missing kid in jose header.");
-    goto error;
-  }
-  if (iss == NULL) {
-    gpr_log(GPR_ERROR, "Missing iss in claims.");
-    goto error;
-  }
-
-  /* This code relies on:
-     https://openid.net/specs/openid-connect-discovery-1_0.html
-     Nobody seems to implement the account/email/webfinger part 2. of the spec
-     so we will rely instead on email/url mappings if we detect such an issuer.
-     Part 4, on the other hand is implemented by both google and salesforce. */
-
-  /* Very non-sophisticated way to detect an email address. Should be good
-     enough for now... */
-  at_sign = strchr(iss, '@');
-  if (at_sign != NULL) {
-    email_key_mapping *mapping;
-    const char *email_domain = at_sign + 1;
-    GPR_ASSERT(ctx->verifier != NULL);
-    mapping = verifier_get_mapping(ctx->verifier, email_domain);
-    if (mapping == NULL) {
-      gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
-      goto error;
-    }
-    req.host = gpr_strdup(mapping->key_url_prefix);
-    path_prefix = strchr(req.host, '/');
-    if (path_prefix == NULL) {
-      gpr_asprintf(&req.http.path, "/%s", iss);
-    } else {
-      *(path_prefix++) = '\0';
-      gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
-    }
-    http_cb = on_keys_retrieved;
-  } else {
-    req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
-    path_prefix = strchr(req.host, '/');
-    if (path_prefix == NULL) {
-      req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
-    } else {
-      *(path_prefix++) = 0;
-      gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
-                   GRPC_OPENID_CONFIG_URL_SUFFIX);
-    }
-    http_cb = on_openid_config_retrieved;
-  }
-
-  grpc_httpcli_get(
-      exec_ctx, &ctx->verifier->http_ctx, &ctx->pops, &req,
-      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
-      http_cb, ctx);
-  gpr_free(req.host);
-  gpr_free(req.http.path);
-  return;
-
-error:
-  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
-  verifier_cb_ctx_destroy(ctx);
-}
-
-void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
-                              grpc_jwt_verifier *verifier,
-                              grpc_pollset *pollset, const char *jwt,
-                              const char *audience,
-                              grpc_jwt_verification_done_cb cb,
-                              void *user_data) {
-  const char *dot = NULL;
-  grpc_json *json;
-  jose_header *header = NULL;
-  grpc_jwt_claims *claims = NULL;
-  gpr_slice header_buffer;
-  gpr_slice claims_buffer;
-  gpr_slice signature;
-  size_t signed_jwt_len;
-  const char *cur = jwt;
-
-  GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
-  dot = strchr(cur, '.');
-  if (dot == NULL) goto error;
-  json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer);
-  if (json == NULL) goto error;
-  header = jose_header_from_json(json, header_buffer);
-  if (header == NULL) goto error;
-
-  cur = dot + 1;
-  dot = strchr(cur, '.');
-  if (dot == NULL) goto error;
-  json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
-  if (json == NULL) goto error;
-  claims = grpc_jwt_claims_from_json(json, claims_buffer);
-  if (claims == NULL) goto error;
-
-  signed_jwt_len = (size_t)(dot - jwt);
-  cur = dot + 1;
-  signature = grpc_base64_decode(cur, 1);
-  if (GPR_SLICE_IS_EMPTY(signature)) goto error;
-  retrieve_key_and_verify(
-      exec_ctx,
-      verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
-                             signature, jwt, signed_jwt_len, user_data, cb));
-  return;
-
-error:
-  if (header != NULL) jose_header_destroy(header);
-  if (claims != NULL) grpc_jwt_claims_destroy(claims);
-  cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
-}
-
-grpc_jwt_verifier *grpc_jwt_verifier_create(
-    const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
-    size_t num_mappings) {
-  grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier));
-  memset(v, 0, sizeof(grpc_jwt_verifier));
-  grpc_httpcli_context_init(&v->http_ctx);
-
-  /* We know at least of one mapping. */
-  v->allocated_mappings = 1 + num_mappings;
-  v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping));
-  verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN,
-                       GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX);
-  /* User-Provided mappings. */
-  if (mappings != NULL) {
-    size_t i;
-    for (i = 0; i < num_mappings; i++) {
-      verifier_put_mapping(v, mappings[i].email_domain,
-                           mappings[i].key_url_prefix);
-    }
-  }
-  return v;
-}
-
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
-  size_t i;
-  if (v == NULL) return;
-  grpc_httpcli_context_destroy(&v->http_ctx);
-  if (v->mappings != NULL) {
-    for (i = 0; i < v->num_mappings; i++) {
-      gpr_free(v->mappings[i].email_domain);
-      gpr_free(v->mappings[i].key_url_prefix);
-    }
-    gpr_free(v->mappings);
-  }
-  gpr_free(v);
-}
diff --git a/src/core/lib/security/jwt_verifier.h b/src/core/lib/security/jwt_verifier.h
deleted file mode 100644
index 98a4f6b..0000000
--- a/src/core/lib/security/jwt_verifier.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_JWT_VERIFIER_H
-#define GRPC_CORE_LIB_SECURITY_JWT_VERIFIER_H
-
-#include "src/core/lib/iomgr/pollset.h"
-#include "src/core/lib/json/json.h"
-
-#include <grpc/support/slice.h>
-#include <grpc/support/time.h>
-
-/* --- Constants. --- */
-
-#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration"
-#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \
-  "developer.gserviceaccount.com"
-#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \
-  "www.googleapis.com/robot/v1/metadata/x509"
-
-/* --- grpc_jwt_verifier_status. --- */
-
-typedef enum {
-  GRPC_JWT_VERIFIER_OK = 0,
-  GRPC_JWT_VERIFIER_BAD_SIGNATURE,
-  GRPC_JWT_VERIFIER_BAD_FORMAT,
-  GRPC_JWT_VERIFIER_BAD_AUDIENCE,
-  GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
-  GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE,
-  GRPC_JWT_VERIFIER_GENERIC_ERROR
-} grpc_jwt_verifier_status;
-
-const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status);
-
-/* --- grpc_jwt_claims. --- */
-
-typedef struct grpc_jwt_claims grpc_jwt_claims;
-
-void grpc_jwt_claims_destroy(grpc_jwt_claims *claims);
-
-/* Returns the whole JSON tree of the claims. */
-const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims);
-
-/* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */
-const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims);
-const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims);
-const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims);
-const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims);
-gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims);
-gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims);
-gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims);
-
-/* --- grpc_jwt_verifier. --- */
-
-typedef struct grpc_jwt_verifier grpc_jwt_verifier;
-
-typedef struct {
-  /* The email domain is the part after the @ sign. */
-  const char *email_domain;
-
-  /* The key url prefix will be used to get the public key from the issuer:
-     https://<key_url_prefix>/<issuer_email>
-     Therefore the key_url_prefix must NOT contain https://. */
-  const char *key_url_prefix;
-} grpc_jwt_verifier_email_domain_key_url_mapping;
-
-/* Globals to control the verifier. Not thread-safe. */
-extern gpr_timespec grpc_jwt_verifier_clock_skew;
-extern gpr_timespec grpc_jwt_verifier_max_delay;
-
-/* The verifier can be created with some custom mappings to help with key
-   discovery in the case where the issuer is an email address.
-   mappings can be NULL in which case num_mappings MUST be 0.
-   A verifier object has one built-in mapping (unless overridden):
-   GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN ->
-   GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/
-grpc_jwt_verifier *grpc_jwt_verifier_create(
-    const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
-    size_t num_mappings);
-
-/*The verifier must not be destroyed if there are still outstanding callbacks.*/
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier);
-
-/* User provided callback that will be called when the verification of the JWT
-   is done (maybe in another thread).
-   It is the responsibility of the callee to call grpc_jwt_claims_destroy on
-   the claims. */
-typedef void (*grpc_jwt_verification_done_cb)(void *user_data,
-                                              grpc_jwt_verifier_status status,
-                                              grpc_jwt_claims *claims);
-
-/* Verifies for the JWT for the given expected audience. */
-void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
-                              grpc_jwt_verifier *verifier,
-                              grpc_pollset *pollset, const char *jwt,
-                              const char *audience,
-                              grpc_jwt_verification_done_cb cb,
-                              void *user_data);
-
-/* --- TESTING ONLY exposed functions. --- */
-
-grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer);
-grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
-                                               const char *audience);
-
-#endif /* GRPC_CORE_LIB_SECURITY_JWT_VERIFIER_H */
diff --git a/src/core/lib/security/secure_endpoint.c b/src/core/lib/security/secure_endpoint.c
deleted file mode 100644
index 27b0e98..0000000
--- a/src/core/lib/security/secure_endpoint.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/secure_endpoint.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/sync.h>
-#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/tsi/transport_security_interface.h"
-
-#define STAGING_BUFFER_SIZE 8192
-
-typedef struct {
-  grpc_endpoint base;
-  grpc_endpoint *wrapped_ep;
-  struct tsi_frame_protector *protector;
-  gpr_mu protector_mu;
-  /* saved upper level callbacks and user_data. */
-  grpc_closure *read_cb;
-  grpc_closure *write_cb;
-  grpc_closure on_read;
-  gpr_slice_buffer *read_buffer;
-  gpr_slice_buffer source_buffer;
-  /* saved handshaker leftover data to unprotect. */
-  gpr_slice_buffer leftover_bytes;
-  /* buffers for read and write */
-  gpr_slice read_staging_buffer;
-
-  gpr_slice write_staging_buffer;
-  gpr_slice_buffer output_buffer;
-
-  gpr_refcount ref;
-} secure_endpoint;
-
-int grpc_trace_secure_endpoint = 0;
-
-static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
-  secure_endpoint *ep = secure_ep;
-  grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep);
-  tsi_frame_protector_destroy(ep->protector);
-  gpr_slice_buffer_destroy(&ep->leftover_bytes);
-  gpr_slice_unref(ep->read_staging_buffer);
-  gpr_slice_unref(ep->write_staging_buffer);
-  gpr_slice_buffer_destroy(&ep->output_buffer);
-  gpr_slice_buffer_destroy(&ep->source_buffer);
-  gpr_mu_destroy(&ep->protector_mu);
-  gpr_free(ep);
-}
-
-/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/
-#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
-#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
-  secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__)
-#define SECURE_ENDPOINT_REF(ep, reason) \
-  secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
-static void secure_endpoint_unref(secure_endpoint *ep,
-                                  grpc_closure_list *closure_list,
-                                  const char *reason, const char *file,
-                                  int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d",
-          ep, reason, ep->ref.count, ep->ref.count - 1);
-  if (gpr_unref(&ep->ref)) {
-    destroy(exec_ctx, ep);
-  }
-}
-
-static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
-                                const char *file, int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP   ref %p : %s %d -> %d",
-          ep, reason, ep->ref.count, ep->ref.count + 1);
-  gpr_ref(&ep->ref);
-}
-#else
-#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
-  secure_endpoint_unref((exec_ctx), (ep))
-#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep))
-static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx,
-                                  secure_endpoint *ep) {
-  if (gpr_unref(&ep->ref)) {
-    destroy(exec_ctx, ep);
-  }
-}
-
-static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
-#endif
-
-static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur,
-                                      uint8_t **end) {
-  gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer);
-  ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
-  *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
-  *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
-}
-
-static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
-                         bool success) {
-  if (grpc_trace_secure_endpoint) {
-    size_t i;
-    for (i = 0; i < ep->read_buffer->count; i++) {
-      char *data = gpr_dump_slice(ep->read_buffer->slices[i],
-                                  GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
-      gpr_free(data);
-    }
-  }
-  ep->read_buffer = NULL;
-  grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success, NULL);
-  SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
-}
-
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
-  unsigned i;
-  uint8_t keep_looping = 0;
-  tsi_result result = TSI_OK;
-  secure_endpoint *ep = (secure_endpoint *)user_data;
-  uint8_t *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
-  uint8_t *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
-
-  if (!success) {
-    gpr_slice_buffer_reset_and_unref(ep->read_buffer);
-    call_read_cb(exec_ctx, ep, 0);
-    return;
-  }
-
-  /* TODO(yangg) check error, maybe bail out early */
-  for (i = 0; i < ep->source_buffer.count; i++) {
-    gpr_slice encrypted = ep->source_buffer.slices[i];
-    uint8_t *message_bytes = GPR_SLICE_START_PTR(encrypted);
-    size_t message_size = GPR_SLICE_LENGTH(encrypted);
-
-    while (message_size > 0 || keep_looping) {
-      size_t unprotected_buffer_size_written = (size_t)(end - cur);
-      size_t processed_message_size = message_size;
-      gpr_mu_lock(&ep->protector_mu);
-      result = tsi_frame_protector_unprotect(ep->protector, message_bytes,
-                                             &processed_message_size, cur,
-                                             &unprotected_buffer_size_written);
-      gpr_mu_unlock(&ep->protector_mu);
-      if (result != TSI_OK) {
-        gpr_log(GPR_ERROR, "Decryption error: %s",
-                tsi_result_to_string(result));
-        break;
-      }
-      message_bytes += processed_message_size;
-      message_size -= processed_message_size;
-      cur += unprotected_buffer_size_written;
-
-      if (cur == end) {
-        flush_read_staging_buffer(ep, &cur, &end);
-        /* Force to enter the loop again to extract buffered bytes in protector.
-           The bytes could be buffered because of running out of staging_buffer.
-           If this happens at the end of all slices, doing another unprotect
-           avoids leaving data in the protector. */
-        keep_looping = 1;
-      } else if (unprotected_buffer_size_written > 0) {
-        keep_looping = 1;
-      } else {
-        keep_looping = 0;
-      }
-    }
-    if (result != TSI_OK) break;
-  }
-
-  if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) {
-    gpr_slice_buffer_add(
-        ep->read_buffer,
-        gpr_slice_split_head(
-            &ep->read_staging_buffer,
-            (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer))));
-  }
-
-  /* TODO(yangg) experiment with moving this block after read_cb to see if it
-     helps latency */
-  gpr_slice_buffer_reset_and_unref(&ep->source_buffer);
-
-  if (result != TSI_OK) {
-    gpr_slice_buffer_reset_and_unref(ep->read_buffer);
-    call_read_cb(exec_ctx, ep, 0);
-    return;
-  }
-
-  call_read_cb(exec_ctx, ep, 1);
-}
-
-static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
-                          gpr_slice_buffer *slices, grpc_closure *cb) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  ep->read_cb = cb;
-  ep->read_buffer = slices;
-  gpr_slice_buffer_reset_and_unref(ep->read_buffer);
-
-  SECURE_ENDPOINT_REF(ep, "read");
-  if (ep->leftover_bytes.count) {
-    gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
-    GPR_ASSERT(ep->leftover_bytes.count == 0);
-    on_read(exec_ctx, ep, 1);
-    return;
-  }
-
-  grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer,
-                     &ep->on_read);
-}
-
-static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur,
-                                       uint8_t **end) {
-  gpr_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer);
-  ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
-  *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
-  *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
-}
-
-static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
-                           gpr_slice_buffer *slices, grpc_closure *cb) {
-  unsigned i;
-  tsi_result result = TSI_OK;
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  uint8_t *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
-  uint8_t *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
-
-  gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
-
-  if (grpc_trace_secure_endpoint) {
-    for (i = 0; i < slices->count; i++) {
-      char *data =
-          gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
-      gpr_free(data);
-    }
-  }
-
-  for (i = 0; i < slices->count; i++) {
-    gpr_slice plain = slices->slices[i];
-    uint8_t *message_bytes = GPR_SLICE_START_PTR(plain);
-    size_t message_size = GPR_SLICE_LENGTH(plain);
-    while (message_size > 0) {
-      size_t protected_buffer_size_to_send = (size_t)(end - cur);
-      size_t processed_message_size = message_size;
-      gpr_mu_lock(&ep->protector_mu);
-      result = tsi_frame_protector_protect(ep->protector, message_bytes,
-                                           &processed_message_size, cur,
-                                           &protected_buffer_size_to_send);
-      gpr_mu_unlock(&ep->protector_mu);
-      if (result != TSI_OK) {
-        gpr_log(GPR_ERROR, "Encryption error: %s",
-                tsi_result_to_string(result));
-        break;
-      }
-      message_bytes += processed_message_size;
-      message_size -= processed_message_size;
-      cur += protected_buffer_size_to_send;
-
-      if (cur == end) {
-        flush_write_staging_buffer(ep, &cur, &end);
-      }
-    }
-    if (result != TSI_OK) break;
-  }
-  if (result == TSI_OK) {
-    size_t still_pending_size;
-    do {
-      size_t protected_buffer_size_to_send = (size_t)(end - cur);
-      gpr_mu_lock(&ep->protector_mu);
-      result = tsi_frame_protector_protect_flush(ep->protector, cur,
-                                                 &protected_buffer_size_to_send,
-                                                 &still_pending_size);
-      gpr_mu_unlock(&ep->protector_mu);
-      if (result != TSI_OK) break;
-      cur += protected_buffer_size_to_send;
-      if (cur == end) {
-        flush_write_staging_buffer(ep, &cur, &end);
-      }
-    } while (still_pending_size > 0);
-    if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) {
-      gpr_slice_buffer_add(
-          &ep->output_buffer,
-          gpr_slice_split_head(
-              &ep->write_staging_buffer,
-              (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer))));
-    }
-  }
-
-  if (result != TSI_OK) {
-    /* TODO(yangg) do different things according to the error type? */
-    gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
-    return;
-  }
-
-  grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb);
-}
-
-static void endpoint_shutdown(grpc_exec_ctx *exec_ctx,
-                              grpc_endpoint *secure_ep) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep);
-}
-
-static void endpoint_destroy(grpc_exec_ctx *exec_ctx,
-                             grpc_endpoint *secure_ep) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy");
-}
-
-static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx,
-                                    grpc_endpoint *secure_ep,
-                                    grpc_pollset *pollset) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset);
-}
-
-static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
-                                        grpc_endpoint *secure_ep,
-                                        grpc_pollset_set *pollset_set) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set);
-}
-
-static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
-  secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  return grpc_endpoint_get_peer(ep->wrapped_ep);
-}
-
-static const grpc_endpoint_vtable vtable = {
-    endpoint_read,           endpoint_write,
-    endpoint_add_to_pollset, endpoint_add_to_pollset_set,
-    endpoint_shutdown,       endpoint_destroy,
-    endpoint_get_peer};
-
-grpc_endpoint *grpc_secure_endpoint_create(
-    struct tsi_frame_protector *protector, grpc_endpoint *transport,
-    gpr_slice *leftover_slices, size_t leftover_nslices) {
-  size_t i;
-  secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint));
-  ep->base.vtable = &vtable;
-  ep->wrapped_ep = transport;
-  ep->protector = protector;
-  gpr_slice_buffer_init(&ep->leftover_bytes);
-  for (i = 0; i < leftover_nslices; i++) {
-    gpr_slice_buffer_add(&ep->leftover_bytes,
-                         gpr_slice_ref(leftover_slices[i]));
-  }
-  ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
-  ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
-  gpr_slice_buffer_init(&ep->output_buffer);
-  gpr_slice_buffer_init(&ep->source_buffer);
-  ep->read_buffer = NULL;
-  grpc_closure_init(&ep->on_read, on_read, ep);
-  gpr_mu_init(&ep->protector_mu);
-  gpr_ref_init(&ep->ref, 1);
-  return &ep->base;
-}
diff --git a/src/core/lib/security/secure_endpoint.h b/src/core/lib/security/secure_endpoint.h
deleted file mode 100644
index ff1c663..0000000
--- a/src/core/lib/security/secure_endpoint.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_SECURE_ENDPOINT_H
-#define GRPC_CORE_LIB_SECURITY_SECURE_ENDPOINT_H
-
-#include <grpc/support/slice.h>
-#include "src/core/lib/iomgr/endpoint.h"
-
-struct tsi_frame_protector;
-
-extern int grpc_trace_secure_endpoint;
-
-/* Takes ownership of protector and to_wrap, and refs leftover_slices. */
-grpc_endpoint *grpc_secure_endpoint_create(
-    struct tsi_frame_protector *protector, grpc_endpoint *to_wrap,
-    gpr_slice *leftover_slices, size_t leftover_nslices);
-
-#endif /* GRPC_CORE_LIB_SECURITY_SECURE_ENDPOINT_H */
diff --git a/src/core/lib/security/security_connector.c b/src/core/lib/security/security_connector.c
deleted file mode 100644
index 2d2023b..0000000
--- a/src/core/lib/security/security_connector.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- *
- * Copyright 2015, 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/security/security_connector.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/ext/transport/chttp2/alpn/alpn.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/handshake.h"
-#include "src/core/lib/security/secure_endpoint.h"
-#include "src/core/lib/security/security_context.h"
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/tsi/fake_transport_security.h"
-#include "src/core/lib/tsi/ssl_transport_security.h"
-
-/* -- Constants. -- */
-
-#ifndef INSTALL_PREFIX
-static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
-#else
-static const char *installed_roots_path =
-    INSTALL_PREFIX "/share/grpc/roots.pem";
-#endif
-
-/* -- Overridden default roots. -- */
-
-static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL;
-
-void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) {
-  ssl_roots_override_cb = cb;
-}
-
-/* -- Cipher suites. -- */
-
-/* Defines the cipher suites that we accept by default. All these cipher suites
-   are compliant with HTTP2. */
-#define GRPC_SSL_CIPHER_SUITES                                            \
-  "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \
-  "SHA384:ECDHE-RSA-AES256-GCM-SHA384"
-
-static gpr_once cipher_suites_once = GPR_ONCE_INIT;
-static const char *cipher_suites = NULL;
-
-static void init_cipher_suites(void) {
-  char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES");
-  cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES;
-}
-
-static const char *ssl_cipher_suites(void) {
-  gpr_once_init(&cipher_suites_once, init_cipher_suites);
-  return cipher_suites;
-}
-
-/* -- Common methods. -- */
-
-/* Returns the first property with that name. */
-const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
-                                                       const char *name) {
-  size_t i;
-  if (peer == NULL) return NULL;
-  for (i = 0; i < peer->property_count; i++) {
-    const tsi_peer_property *property = &peer->properties[i];
-    if (name == NULL && property->name == NULL) {
-      return property;
-    }
-    if (name != NULL && property->name != NULL &&
-        strcmp(property->name, name) == 0) {
-      return property;
-    }
-  }
-  return NULL;
-}
-
-void grpc_server_security_connector_shutdown(
-    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) {
-  grpc_security_connector_handshake_list *tmp;
-  gpr_mu_lock(&connector->mu);
-  while (connector->handshaking_handshakes) {
-    tmp = connector->handshaking_handshakes;
-    grpc_security_handshake_shutdown(
-        exec_ctx, connector->handshaking_handshakes->handshake);
-    connector->handshaking_handshakes = tmp->next;
-    gpr_free(tmp);
-  }
-  gpr_mu_unlock(&connector->mu);
-}
-
-void grpc_channel_security_connector_do_handshake(
-    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
-    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
-    void *user_data) {
-  if (sc == NULL || nonsecure_endpoint == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
-  } else {
-    sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
-  }
-}
-
-void grpc_server_security_connector_do_handshake(
-    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
-    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
-    grpc_security_handshake_done_cb cb, void *user_data) {
-  if (sc == NULL || nonsecure_endpoint == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
-  } else {
-    sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data);
-  }
-}
-
-void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
-                                        grpc_security_connector *sc,
-                                        tsi_peer peer,
-                                        grpc_security_peer_check_cb cb,
-                                        void *user_data) {
-  if (sc == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
-    tsi_peer_destruct(&peer);
-  } else {
-    sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data);
-  }
-}
-
-void grpc_channel_security_connector_check_call_host(
-    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
-    const char *host, grpc_auth_context *auth_context,
-    grpc_security_call_host_check_cb cb, void *user_data) {
-  if (sc == NULL || sc->check_call_host == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR);
-  } else {
-    sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data);
-  }
-}
-
-#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
-grpc_security_connector *grpc_security_connector_ref(
-    grpc_security_connector *sc, const char *file, int line,
-    const char *reason) {
-  if (sc == NULL) return NULL;
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "SECURITY_CONNECTOR:%p   ref %d -> %d %s", sc,
-          (int)sc->refcount.count, (int)sc->refcount.count + 1, reason);
-#else
-grpc_security_connector *grpc_security_connector_ref(
-    grpc_security_connector *sc) {
-  if (sc == NULL) return NULL;
-#endif
-  gpr_ref(&sc->refcount);
-  return sc;
-}
-
-#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
-void grpc_security_connector_unref(grpc_security_connector *sc,
-                                   const char *file, int line,
-                                   const char *reason) {
-  if (sc == NULL) return;
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc,
-          (int)sc->refcount.count, (int)sc->refcount.count - 1, reason);
-#else
-void grpc_security_connector_unref(grpc_security_connector *sc) {
-  if (sc == NULL) return;
-#endif
-  if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc);
-}
-
-static void connector_pointer_arg_destroy(void *p) {
-  GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg");
-}
-
-static void *connector_pointer_arg_copy(void *p) {
-  return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg");
-}
-
-static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
-
-static const grpc_arg_pointer_vtable connector_pointer_vtable = {
-    connector_pointer_arg_copy, connector_pointer_arg_destroy,
-    connector_pointer_cmp};
-
-grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
-  grpc_arg result;
-  result.type = GRPC_ARG_POINTER;
-  result.key = GRPC_SECURITY_CONNECTOR_ARG;
-  result.value.pointer.vtable = &connector_pointer_vtable;
-  result.value.pointer.p = sc;
-  return result;
-}
-
-grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) {
-  if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL;
-  if (arg->type != GRPC_ARG_POINTER) {
-    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
-            GRPC_SECURITY_CONNECTOR_ARG);
-    return NULL;
-  }
-  return arg->value.pointer.p;
-}
-
-grpc_security_connector *grpc_find_security_connector_in_args(
-    const grpc_channel_args *args) {
-  size_t i;
-  if (args == NULL) return NULL;
-  for (i = 0; i < args->num_args; i++) {
-    grpc_security_connector *sc =
-        grpc_security_connector_from_arg(&args->args[i]);
-    if (sc != NULL) return sc;
-  }
-  return NULL;
-}
-
-/* -- Fake implementation. -- */
-
-static void fake_channel_destroy(grpc_security_connector *sc) {
-  grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
-  grpc_call_credentials_unref(c->request_metadata_creds);
-  gpr_free(sc);
-}
-
-static void fake_server_destroy(grpc_security_connector *sc) {
-  grpc_server_security_connector *c = (grpc_server_security_connector *)sc;
-  gpr_mu_destroy(&c->mu);
-  gpr_free(sc);
-}
-
-static void fake_check_peer(grpc_exec_ctx *exec_ctx,
-                            grpc_security_connector *sc, tsi_peer peer,
-                            grpc_security_peer_check_cb cb, void *user_data) {
-  const char *prop_name;
-  grpc_security_status status = GRPC_SECURITY_OK;
-  grpc_auth_context *auth_context = NULL;
-  if (peer.property_count != 1) {
-    gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
-    status = GRPC_SECURITY_ERROR;
-    goto end;
-  }
-  prop_name = peer.properties[0].name;
-  if (prop_name == NULL ||
-      strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) {
-    gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.",
-            prop_name == NULL ? "<EMPTY>" : prop_name);
-    status = GRPC_SECURITY_ERROR;
-    goto end;
-  }
-  if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE,
-              peer.properties[0].value.length)) {
-    gpr_log(GPR_ERROR, "Invalid value for cert type property.");
-    status = GRPC_SECURITY_ERROR;
-    goto end;
-  }
-  auth_context = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(
-      auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
-      GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
-
-end:
-  cb(exec_ctx, user_data, status, auth_context);
-  grpc_auth_context_unref(auth_context);
-  tsi_peer_destruct(&peer);
-}
-
-static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
-                                         grpc_channel_security_connector *sc,
-                                         const char *host,
-                                         grpc_auth_context *auth_context,
-                                         grpc_security_call_host_check_cb cb,
-                                         void *user_data) {
-  cb(exec_ctx, user_data, GRPC_SECURITY_OK);
-}
-
-static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
-                                      grpc_channel_security_connector *sc,
-                                      grpc_endpoint *nonsecure_endpoint,
-                                      grpc_security_handshake_done_cb cb,
-                                      void *user_data) {
-  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
-                             true, nonsecure_endpoint, cb, user_data);
-}
-
-static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
-                                     grpc_server_security_connector *sc,
-                                     grpc_tcp_server_acceptor *acceptor,
-                                     grpc_endpoint *nonsecure_endpoint,
-                                     grpc_security_handshake_done_cb cb,
-                                     void *user_data) {
-  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
-                             false, nonsecure_endpoint, cb, user_data);
-}
-
-static grpc_security_connector_vtable fake_channel_vtable = {
-    fake_channel_destroy, fake_check_peer};
-
-static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy,
-                                                            fake_check_peer};
-
-grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds) {
-  grpc_channel_security_connector *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
-  c->base.vtable = &fake_channel_vtable;
-  c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds);
-  c->check_call_host = fake_channel_check_call_host;
-  c->do_handshake = fake_channel_do_handshake;
-  return c;
-}
-
-grpc_server_security_connector *grpc_fake_server_security_connector_create(
-    void) {
-  grpc_server_security_connector *c =
-      gpr_malloc(sizeof(grpc_server_security_connector));
-  memset(c, 0, sizeof(*c));
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.vtable = &fake_server_vtable;
-  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
-  c->do_handshake = fake_server_do_handshake;
-  gpr_mu_init(&c->mu);
-  return c;
-}
-
-/* --- Ssl implementation. --- */
-
-typedef struct {
-  grpc_channel_security_connector base;
-  tsi_ssl_handshaker_factory *handshaker_factory;
-  char *target_name;
-  char *overridden_target_name;
-} grpc_ssl_channel_security_connector;
-
-typedef struct {
-  grpc_server_security_connector base;
-  tsi_ssl_handshaker_factory *handshaker_factory;
-} grpc_ssl_server_security_connector;
-
-static void ssl_channel_destroy(grpc_security_connector *sc) {
-  grpc_ssl_channel_security_connector *c =
-      (grpc_ssl_channel_security_connector *)sc;
-  grpc_call_credentials_unref(c->base.request_metadata_creds);
-  if (c->handshaker_factory != NULL) {
-    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
-  }
-  if (c->target_name != NULL) gpr_free(c->target_name);
-  if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
-  gpr_free(sc);
-}
-
-static void ssl_server_destroy(grpc_security_connector *sc) {
-  grpc_ssl_server_security_connector *c =
-      (grpc_ssl_server_security_connector *)sc;
-
-  if (c->handshaker_factory != NULL) {
-    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
-  }
-  gpr_mu_destroy(&c->base.mu);
-  gpr_free(sc);
-}
-
-static grpc_security_status ssl_create_handshaker(
-    tsi_ssl_handshaker_factory *handshaker_factory, bool is_client,
-    const char *peer_name, tsi_handshaker **handshaker) {
-  tsi_result result = TSI_OK;
-  if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
-  result = tsi_ssl_handshaker_factory_create_handshaker(
-      handshaker_factory, is_client ? peer_name : NULL, handshaker);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
-            tsi_result_to_string(result));
-    return GRPC_SECURITY_ERROR;
-  }
-  return GRPC_SECURITY_OK;
-}
-
-static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
-                                     grpc_channel_security_connector *sc,
-                                     grpc_endpoint *nonsecure_endpoint,
-                                     grpc_security_handshake_done_cb cb,
-                                     void *user_data) {
-  grpc_ssl_channel_security_connector *c =
-      (grpc_ssl_channel_security_connector *)sc;
-  tsi_handshaker *handshaker;
-  grpc_security_status status = ssl_create_handshaker(
-      c->handshaker_factory, true,
-      c->overridden_target_name != NULL ? c->overridden_target_name
-                                        : c->target_name,
-      &handshaker);
-  if (status != GRPC_SECURITY_OK) {
-    cb(exec_ctx, user_data, status, NULL, NULL);
-  } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
-                               nonsecure_endpoint, cb, user_data);
-  }
-}
-
-static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
-                                    grpc_server_security_connector *sc,
-                                    grpc_tcp_server_acceptor *acceptor,
-                                    grpc_endpoint *nonsecure_endpoint,
-                                    grpc_security_handshake_done_cb cb,
-                                    void *user_data) {
-  grpc_ssl_server_security_connector *c =
-      (grpc_ssl_server_security_connector *)sc;
-  tsi_handshaker *handshaker;
-  grpc_security_status status =
-      ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker);
-  if (status != GRPC_SECURITY_OK) {
-    cb(exec_ctx, user_data, status, NULL, NULL);
-  } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
-                               nonsecure_endpoint, cb, user_data);
-  }
-}
-
-static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
-  char *allocated_name = NULL;
-  int r;
-
-  if (strchr(peer_name, ':') != NULL) {
-    char *ignored_port;
-    gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
-    gpr_free(ignored_port);
-    peer_name = allocated_name;
-    if (!peer_name) return 0;
-  }
-  r = tsi_ssl_peer_matches_name(peer, peer_name);
-  gpr_free(allocated_name);
-  return r;
-}
-
-grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
-  size_t i;
-  grpc_auth_context *ctx = NULL;
-  const char *peer_identity_property_name = NULL;
-
-  /* The caller has checked the certificate type property. */
-  GPR_ASSERT(peer->property_count >= 1);
-  ctx = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(
-      ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
-      GRPC_SSL_TRANSPORT_SECURITY_TYPE);
-  for (i = 0; i < peer->property_count; i++) {
-    const tsi_peer_property *prop = &peer->properties[i];
-    if (prop->name == NULL) continue;
-    if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
-      /* If there is no subject alt name, have the CN as the identity. */
-      if (peer_identity_property_name == NULL) {
-        peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME;
-      }
-      grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME,
-                                     prop->value.data, prop->value.length);
-    } else if (strcmp(prop->name,
-                      TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
-      peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME;
-      grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME,
-                                     prop->value.data, prop->value.length);
-    } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) {
-      grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME,
-                                     prop->value.data, prop->value.length);
-    }
-  }
-  if (peer_identity_property_name != NULL) {
-    GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
-                   ctx, peer_identity_property_name) == 1);
-  }
-  return ctx;
-}
-
-static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
-                                           const char *peer_name,
-                                           const tsi_peer *peer,
-                                           grpc_auth_context **auth_context) {
-  /* Check the ALPN. */
-  const tsi_peer_property *p =
-      tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
-  if (p == NULL) {
-    gpr_log(GPR_ERROR, "Missing selected ALPN property.");
-    return GRPC_SECURITY_ERROR;
-  }
-  if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) {
-    gpr_log(GPR_ERROR, "Invalid ALPN value.");
-    return GRPC_SECURITY_ERROR;
-  }
-
-  /* Check the peer name if specified. */
-  if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) {
-    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
-    return GRPC_SECURITY_ERROR;
-  }
-  *auth_context = tsi_ssl_peer_to_auth_context(peer);
-  return GRPC_SECURITY_OK;
-}
-
-static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx,
-                                   grpc_security_connector *sc, tsi_peer peer,
-                                   grpc_security_peer_check_cb cb,
-                                   void *user_data) {
-  grpc_ssl_channel_security_connector *c =
-      (grpc_ssl_channel_security_connector *)sc;
-  grpc_security_status status;
-  grpc_auth_context *auth_context = NULL;
-  status = ssl_check_peer(sc, c->overridden_target_name != NULL
-                                  ? c->overridden_target_name
-                                  : c->target_name,
-                          &peer, &auth_context);
-  cb(exec_ctx, user_data, status, auth_context);
-  grpc_auth_context_unref(auth_context);
-  tsi_peer_destruct(&peer);
-}
-
-static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx,
-                                  grpc_security_connector *sc, tsi_peer peer,
-                                  grpc_security_peer_check_cb cb,
-                                  void *user_data) {
-  grpc_auth_context *auth_context = NULL;
-  grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context);
-  tsi_peer_destruct(&peer);
-  cb(exec_ctx, user_data, status, auth_context);
-  grpc_auth_context_unref(auth_context);
-}
-
-static void add_shallow_auth_property_to_peer(tsi_peer *peer,
-                                              const grpc_auth_property *prop,
-                                              const char *tsi_prop_name) {
-  tsi_peer_property *tsi_prop = &peer->properties[peer->property_count++];
-  tsi_prop->name = (char *)tsi_prop_name;
-  tsi_prop->value.data = prop->value;
-  tsi_prop->value.length = prop->value_length;
-}
-
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
-    const grpc_auth_context *auth_context) {
-  size_t max_num_props = 0;
-  grpc_auth_property_iterator it;
-  const grpc_auth_property *prop;
-  tsi_peer peer;
-  memset(&peer, 0, sizeof(peer));
-
-  it = grpc_auth_context_property_iterator(auth_context);
-  while (grpc_auth_property_iterator_next(&it) != NULL) max_num_props++;
-
-  if (max_num_props > 0) {
-    peer.properties = gpr_malloc(max_num_props * sizeof(tsi_peer_property));
-    it = grpc_auth_context_property_iterator(auth_context);
-    while ((prop = grpc_auth_property_iterator_next(&it)) != NULL) {
-      if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) {
-        add_shallow_auth_property_to_peer(
-            &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY);
-      } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) {
-        add_shallow_auth_property_to_peer(
-            &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
-      } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) {
-        add_shallow_auth_property_to_peer(&peer, prop,
-                                          TSI_X509_PEM_CERT_PROPERTY);
-      }
-    }
-  }
-  return peer;
-}
-
-void tsi_shallow_peer_destruct(tsi_peer *peer) {
-  if (peer->properties != NULL) gpr_free(peer->properties);
-}
-
-static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
-                                        grpc_channel_security_connector *sc,
-                                        const char *host,
-                                        grpc_auth_context *auth_context,
-                                        grpc_security_call_host_check_cb cb,
-                                        void *user_data) {
-  grpc_ssl_channel_security_connector *c =
-      (grpc_ssl_channel_security_connector *)sc;
-  grpc_security_status status = GRPC_SECURITY_ERROR;
-  tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context);
-  if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
-
-  /* If the target name was overridden, then the original target_name was
-     'checked' transitively during the previous peer check at the end of the
-     handshake. */
-  if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
-    status = GRPC_SECURITY_OK;
-  }
-  cb(exec_ctx, user_data, status);
-  tsi_shallow_peer_destruct(&peer);
-}
-
-static grpc_security_connector_vtable ssl_channel_vtable = {
-    ssl_channel_destroy, ssl_channel_check_peer};
-
-static grpc_security_connector_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_check_peer};
-
-static gpr_slice compute_default_pem_root_certs_once(void) {
-  gpr_slice result = gpr_empty_slice();
-
-  /* First try to load the roots from the environment. */
-  char *default_root_certs_path =
-      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
-  if (default_root_certs_path != NULL) {
-    result = gpr_load_file(default_root_certs_path, 0, NULL);
-    gpr_free(default_root_certs_path);
-  }
-
-  /* Try overridden roots if needed. */
-  grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
-  if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) {
-    char *pem_root_certs = NULL;
-    ovrd_res = ssl_roots_override_cb(&pem_root_certs);
-    if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) {
-      GPR_ASSERT(pem_root_certs != NULL);
-      result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free);
-    }
-  }
-
-  /* Fall back to installed certs if needed. */
-  if (GPR_SLICE_IS_EMPTY(result) &&
-      ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
-    result = gpr_load_file(installed_roots_path, 0, NULL);
-  }
-  return result;
-}
-
-static gpr_slice default_pem_root_certs;
-
-static void init_default_pem_root_certs(void) {
-  default_pem_root_certs = compute_default_pem_root_certs_once();
-}
-
-gpr_slice grpc_get_default_ssl_roots_for_testing(void) {
-  return compute_default_pem_root_certs_once();
-}
-
-static tsi_client_certificate_request_type
-get_tsi_client_certificate_request_type(
-    grpc_ssl_client_certificate_request_type grpc_request_type) {
-  switch (grpc_request_type) {
-    case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE:
-      return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
-
-    case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
-      return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
-
-    case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
-      return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY;
-
-    case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
-      return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
-
-    case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
-      return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
-
-    default:
-      // Is this a sane default
-      return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
-  }
-}
-
-size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
-  /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
-     loading all the roots once for the lifetime of the process. */
-  static gpr_once once = GPR_ONCE_INIT;
-  gpr_once_init(&once, init_default_pem_root_certs);
-  *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs);
-  return GPR_SLICE_LENGTH(default_pem_root_certs);
-}
-
-grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds,
-    const grpc_ssl_config *config, const char *target_name,
-    const char *overridden_target_name, grpc_channel_security_connector **sc) {
-  size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
-  const unsigned char **alpn_protocol_strings =
-      gpr_malloc(sizeof(const char *) * num_alpn_protocols);
-  unsigned char *alpn_protocol_string_lengths =
-      gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
-  tsi_result result = TSI_OK;
-  grpc_ssl_channel_security_connector *c;
-  size_t i;
-  const unsigned char *pem_root_certs;
-  size_t pem_root_certs_size;
-  char *port;
-
-  for (i = 0; i < num_alpn_protocols; i++) {
-    alpn_protocol_strings[i] =
-        (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
-    alpn_protocol_string_lengths[i] =
-        (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i));
-  }
-
-  if (config == NULL || target_name == NULL) {
-    gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
-    goto error;
-  }
-  if (config->pem_root_certs == NULL) {
-    pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
-    if (pem_root_certs == NULL || pem_root_certs_size == 0) {
-      gpr_log(GPR_ERROR, "Could not get default pem root certs.");
-      goto error;
-    }
-  } else {
-    pem_root_certs = config->pem_root_certs;
-    pem_root_certs_size = config->pem_root_certs_size;
-  }
-
-  c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector));
-  memset(c, 0, sizeof(grpc_ssl_channel_security_connector));
-
-  gpr_ref_init(&c->base.base.refcount, 1);
-  c->base.base.vtable = &ssl_channel_vtable;
-  c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
-  c->base.request_metadata_creds =
-      grpc_call_credentials_ref(request_metadata_creds);
-  c->base.check_call_host = ssl_channel_check_call_host;
-  c->base.do_handshake = ssl_channel_do_handshake;
-  gpr_split_host_port(target_name, &c->target_name, &port);
-  gpr_free(port);
-  if (overridden_target_name != NULL) {
-    c->overridden_target_name = gpr_strdup(overridden_target_name);
-  }
-  result = tsi_create_ssl_client_handshaker_factory(
-      config->pem_private_key, config->pem_private_key_size,
-      config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
-      pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings,
-      alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols,
-      &c->handshaker_factory);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
-            tsi_result_to_string(result));
-    ssl_channel_destroy(&c->base.base);
-    *sc = NULL;
-    goto error;
-  }
-  *sc = &c->base;
-  gpr_free((void *)alpn_protocol_strings);
-  gpr_free(alpn_protocol_string_lengths);
-  return GRPC_SECURITY_OK;
-
-error:
-  gpr_free((void *)alpn_protocol_strings);
-  gpr_free(alpn_protocol_string_lengths);
-  return GRPC_SECURITY_ERROR;
-}
-
-grpc_security_status grpc_ssl_server_security_connector_create(
-    const grpc_ssl_server_config *config, grpc_server_security_connector **sc) {
-  size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
-  const unsigned char **alpn_protocol_strings =
-      gpr_malloc(sizeof(const char *) * num_alpn_protocols);
-  unsigned char *alpn_protocol_string_lengths =
-      gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
-  tsi_result result = TSI_OK;
-  grpc_ssl_server_security_connector *c;
-  size_t i;
-
-  for (i = 0; i < num_alpn_protocols; i++) {
-    alpn_protocol_strings[i] =
-        (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
-    alpn_protocol_string_lengths[i] =
-        (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i));
-  }
-
-  if (config == NULL || config->num_key_cert_pairs == 0) {
-    gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
-    goto error;
-  }
-  c = gpr_malloc(sizeof(grpc_ssl_server_security_connector));
-  memset(c, 0, sizeof(grpc_ssl_server_security_connector));
-
-  gpr_ref_init(&c->base.base.refcount, 1);
-  c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
-  c->base.base.vtable = &ssl_server_vtable;
-  result = tsi_create_ssl_server_handshaker_factory_ex(
-      (const unsigned char **)config->pem_private_keys,
-      config->pem_private_keys_sizes,
-      (const unsigned char **)config->pem_cert_chains,
-      config->pem_cert_chains_sizes, config->num_key_cert_pairs,
-      config->pem_root_certs, config->pem_root_certs_size,
-      get_tsi_client_certificate_request_type(
-          config->client_certificate_request),
-      ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths,
-      (uint16_t)num_alpn_protocols, &c->handshaker_factory);
-  if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
-            tsi_result_to_string(result));
-    ssl_server_destroy(&c->base.base);
-    *sc = NULL;
-    goto error;
-  }
-  gpr_mu_init(&c->base.mu);
-  c->base.do_handshake = ssl_server_do_handshake;
-  *sc = &c->base;
-  gpr_free((void *)alpn_protocol_strings);
-  gpr_free(alpn_protocol_string_lengths);
-  return GRPC_SECURITY_OK;
-
-error:
-  gpr_free((void *)alpn_protocol_strings);
-  gpr_free(alpn_protocol_string_lengths);
-  return GRPC_SECURITY_ERROR;
-}
diff --git a/src/core/lib/security/security_connector.h b/src/core/lib/security/security_connector.h
deleted file mode 100644
index 2c893cd..0000000
--- a/src/core/lib/security/security_connector.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_SECURITY_CONNECTOR_H
-#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_H
-
-#include <grpc/grpc_security.h>
-#include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/iomgr/tcp_server.h"
-#include "src/core/lib/tsi/transport_security_interface.h"
-
-/* --- status enum. --- */
-
-typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
-
-/* --- URL schemes. --- */
-
-#define GRPC_SSL_URL_SCHEME "https"
-#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security"
-
-/* --- security_connector object. ---
-
-    A security connector object represents away to configure the underlying
-    transport security mechanism and check the resulting trusted peer.  */
-
-typedef struct grpc_security_connector grpc_security_connector;
-
-#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
-
-typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx,
-                                            void *user_data,
-                                            grpc_security_status status,
-                                            grpc_auth_context *auth_context);
-
-/* Ownership of the secure_endpoint is transfered. */
-typedef void (*grpc_security_handshake_done_cb)(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status,
-    grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context);
-
-typedef struct {
-  void (*destroy)(grpc_security_connector *sc);
-  void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
-                     tsi_peer peer, grpc_security_peer_check_cb cb,
-                     void *user_data);
-} grpc_security_connector_vtable;
-
-typedef struct grpc_security_connector_handshake_list {
-  void *handshake;
-  struct grpc_security_connector_handshake_list *next;
-} grpc_security_connector_handshake_list;
-
-struct grpc_security_connector {
-  const grpc_security_connector_vtable *vtable;
-  gpr_refcount refcount;
-  const char *url_scheme;
-};
-
-/* Refcounting. */
-#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
-#define GRPC_SECURITY_CONNECTOR_REF(p, r) \
-  grpc_security_connector_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \
-  grpc_security_connector_unref((p), __FILE__, __LINE__, (r))
-grpc_security_connector *grpc_security_connector_ref(
-    grpc_security_connector *policy, const char *file, int line,
-    const char *reason);
-void grpc_security_connector_unref(grpc_security_connector *policy,
-                                   const char *file, int line,
-                                   const char *reason);
-#else
-#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p))
-#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p))
-grpc_security_connector *grpc_security_connector_ref(
-    grpc_security_connector *policy);
-void grpc_security_connector_unref(grpc_security_connector *policy);
-#endif
-
-/* Check the peer. Callee takes ownership of the peer object.
-   The callback will include the resulting auth_context. */
-void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
-                                        grpc_security_connector *sc,
-                                        tsi_peer peer,
-                                        grpc_security_peer_check_cb cb,
-                                        void *user_data);
-
-/* Util to encapsulate the connector in a channel arg. */
-grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
-
-/* Util to get the connector from a channel arg. */
-grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg);
-
-/* Util to find the connector from channel args. */
-grpc_security_connector *grpc_find_security_connector_in_args(
-    const grpc_channel_args *args);
-
-/* --- channel_security_connector object. ---
-
-    A channel security connector object represents away to configure the
-    underlying transport security mechanism on the client side.  */
-
-typedef struct grpc_channel_security_connector grpc_channel_security_connector;
-
-typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
-                                                 void *user_data,
-                                                 grpc_security_status status);
-
-struct grpc_channel_security_connector {
-  grpc_security_connector base;
-  grpc_call_credentials *request_metadata_creds;
-  void (*check_call_host)(grpc_exec_ctx *exec_ctx,
-                          grpc_channel_security_connector *sc, const char *host,
-                          grpc_auth_context *auth_context,
-                          grpc_security_call_host_check_cb cb, void *user_data);
-  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
-                       grpc_channel_security_connector *sc,
-                       grpc_endpoint *nonsecure_endpoint,
-                       grpc_security_handshake_done_cb cb, void *user_data);
-};
-
-/* Checks that the host that will be set for a call is acceptable. */
-void grpc_channel_security_connector_check_call_host(
-    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
-    const char *host, grpc_auth_context *auth_context,
-    grpc_security_call_host_check_cb cb, void *user_data);
-
-/* Handshake. */
-void grpc_channel_security_connector_do_handshake(
-    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
-    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
-    void *user_data);
-
-/* --- server_security_connector object. ---
-
-    A server security connector object represents away to configure the
-    underlying transport security mechanism on the server side.  */
-
-typedef struct grpc_server_security_connector grpc_server_security_connector;
-
-struct grpc_server_security_connector {
-  grpc_security_connector base;
-  gpr_mu mu;
-  grpc_security_connector_handshake_list *handshaking_handshakes;
-  const grpc_channel_args *channel_args;
-  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
-                       grpc_server_security_connector *sc,
-                       grpc_tcp_server_acceptor *acceptor,
-                       grpc_endpoint *nonsecure_endpoint,
-                       grpc_security_handshake_done_cb cb, void *user_data);
-};
-
-void grpc_server_security_connector_do_handshake(
-    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
-    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
-    grpc_security_handshake_done_cb cb, void *user_data);
-
-void grpc_server_security_connector_shutdown(
-    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
-
-/* --- Creation security connectors. --- */
-
-/* For TESTING ONLY!
-   Creates a fake connector that emulates real channel security.  */
-grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds);
-
-/* For TESTING ONLY!
-   Creates a fake connector that emulates real server security.  */
-grpc_server_security_connector *grpc_fake_server_security_connector_create(
-    void);
-
-/* Config for ssl clients. */
-typedef struct {
-  unsigned char *pem_private_key;
-  size_t pem_private_key_size;
-  unsigned char *pem_cert_chain;
-  size_t pem_cert_chain_size;
-  unsigned char *pem_root_certs;
-  size_t pem_root_certs_size;
-} grpc_ssl_config;
-
-/* Creates an SSL channel_security_connector.
-   - request_metadata_creds is the credentials object which metadata
-     will be sent with each request. This parameter can be NULL.
-   - config is the SSL config to be used for the SSL channel establishment.
-   - is_client should be 0 for a server or a non-0 value for a client.
-   - secure_peer_name is the secure peer name that should be checked in
-     grpc_channel_security_connector_check_peer. This parameter may be NULL in
-     which case the peer name will not be checked. Note that if this parameter
-     is not NULL, then, pem_root_certs should not be NULL either.
-   - sc is a pointer on the connector to be created.
-  This function returns GRPC_SECURITY_OK in case of success or a
-  specific error code otherwise.
-*/
-grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds,
-    const grpc_ssl_config *config, const char *target_name,
-    const char *overridden_target_name, grpc_channel_security_connector **sc);
-
-/* Gets the default ssl roots. */
-size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);
-
-/* Exposed for TESTING ONLY!. */
-gpr_slice grpc_get_default_ssl_roots_for_testing(void);
-
-/* Config for ssl servers. */
-typedef struct {
-  unsigned char **pem_private_keys;
-  size_t *pem_private_keys_sizes;
-  unsigned char **pem_cert_chains;
-  size_t *pem_cert_chains_sizes;
-  size_t num_key_cert_pairs;
-  unsigned char *pem_root_certs;
-  size_t pem_root_certs_size;
-  grpc_ssl_client_certificate_request_type client_certificate_request;
-} grpc_ssl_server_config;
-
-/* Creates an SSL server_security_connector.
-   - config is the SSL config to be used for the SSL channel establishment.
-   - sc is a pointer on the connector to be created.
-  This function returns GRPC_SECURITY_OK in case of success or a
-  specific error code otherwise.
-*/
-grpc_security_status grpc_ssl_server_security_connector_create(
-    const grpc_ssl_server_config *config, grpc_server_security_connector **sc);
-
-/* Util. */
-const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
-                                                       const char *name);
-
-/* Exposed for testing only. */
-grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer);
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
-    const grpc_auth_context *auth_context);
-void tsi_shallow_peer_destruct(tsi_peer *peer);
-
-#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_H */
diff --git a/src/core/lib/security/security_context.c b/src/core/lib/security/security_context.c
deleted file mode 100644
index 343e0b5..0000000
--- a/src/core/lib/security/security_context.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <string.h>
-
-#include "src/core/lib/security/security_context.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/surface/api_trace.h"
-#include "src/core/lib/surface/call.h"
-
-#include <grpc/grpc_security.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-/* --- grpc_call --- */
-
-grpc_call_error grpc_call_set_credentials(grpc_call *call,
-                                          grpc_call_credentials *creds) {
-  grpc_client_security_context *ctx = NULL;
-  GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
-                 (call, creds));
-  if (!grpc_call_is_client(call)) {
-    gpr_log(GPR_ERROR, "Method is client-side only.");
-    return GRPC_CALL_ERROR_NOT_ON_SERVER;
-  }
-  ctx = (grpc_client_security_context *)grpc_call_context_get(
-      call, GRPC_CONTEXT_SECURITY);
-  if (ctx == NULL) {
-    ctx = grpc_client_security_context_create();
-    ctx->creds = grpc_call_credentials_ref(creds);
-    grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
-                          grpc_client_security_context_destroy);
-  } else {
-    grpc_call_credentials_unref(ctx->creds);
-    ctx->creds = grpc_call_credentials_ref(creds);
-  }
-  return GRPC_CALL_OK;
-}
-
-grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
-  void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
-  GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call));
-  if (sec_ctx == NULL) return NULL;
-  return grpc_call_is_client(call)
-             ? GRPC_AUTH_CONTEXT_REF(
-                   ((grpc_client_security_context *)sec_ctx)->auth_context,
-                   "grpc_call_auth_context client")
-             : GRPC_AUTH_CONTEXT_REF(
-                   ((grpc_server_security_context *)sec_ctx)->auth_context,
-                   "grpc_call_auth_context server");
-}
-
-void grpc_auth_context_release(grpc_auth_context *context) {
-  GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context));
-  GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref");
-}
-
-/* --- grpc_client_security_context --- */
-
-grpc_client_security_context *grpc_client_security_context_create(void) {
-  grpc_client_security_context *ctx =
-      gpr_malloc(sizeof(grpc_client_security_context));
-  memset(ctx, 0, sizeof(grpc_client_security_context));
-  return ctx;
-}
-
-void grpc_client_security_context_destroy(void *ctx) {
-  grpc_client_security_context *c = (grpc_client_security_context *)ctx;
-  grpc_call_credentials_unref(c->creds);
-  GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context");
-  gpr_free(ctx);
-}
-
-/* --- grpc_server_security_context --- */
-
-grpc_server_security_context *grpc_server_security_context_create(void) {
-  grpc_server_security_context *ctx =
-      gpr_malloc(sizeof(grpc_server_security_context));
-  memset(ctx, 0, sizeof(grpc_server_security_context));
-  return ctx;
-}
-
-void grpc_server_security_context_destroy(void *ctx) {
-  grpc_server_security_context *c = (grpc_server_security_context *)ctx;
-  GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context");
-  gpr_free(ctx);
-}
-
-/* --- grpc_auth_context --- */
-
-static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
-
-grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
-  grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
-  memset(ctx, 0, sizeof(grpc_auth_context));
-  gpr_ref_init(&ctx->refcount, 1);
-  if (chained != NULL) {
-    ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
-    ctx->peer_identity_property_name =
-        ctx->chained->peer_identity_property_name;
-  }
-  return ctx;
-}
-
-#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
-grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx,
-                                         const char *file, int line,
-                                         const char *reason) {
-  if (ctx == NULL) return NULL;
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "AUTH_CONTEXT:%p   ref %d -> %d %s", ctx, (int)ctx->refcount.count,
-          (int)ctx->refcount.count + 1, reason);
-#else
-grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) {
-  if (ctx == NULL) return NULL;
-#endif
-  gpr_ref(&ctx->refcount);
-  return ctx;
-}
-
-#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
-void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line,
-                             const char *reason) {
-  if (ctx == NULL) return;
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count,
-          (int)ctx->refcount.count - 1, reason);
-#else
-void grpc_auth_context_unref(grpc_auth_context *ctx) {
-  if (ctx == NULL) return;
-#endif
-  if (gpr_unref(&ctx->refcount)) {
-    size_t i;
-    GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained");
-    if (ctx->properties.array != NULL) {
-      for (i = 0; i < ctx->properties.count; i++) {
-        grpc_auth_property_reset(&ctx->properties.array[i]);
-      }
-      gpr_free(ctx->properties.array);
-    }
-    gpr_free(ctx);
-  }
-}
-
-const char *grpc_auth_context_peer_identity_property_name(
-    const grpc_auth_context *ctx) {
-  GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1,
-                 (ctx));
-  return ctx->peer_identity_property_name;
-}
-
-int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
-                                                      const char *name) {
-  grpc_auth_property_iterator it =
-      grpc_auth_context_find_properties_by_name(ctx, name);
-  const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
-  GRPC_API_TRACE(
-      "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2,
-      (ctx, name));
-  if (prop == NULL) {
-    gpr_log(GPR_ERROR, "Property name %s not found in auth context.",
-            name != NULL ? name : "NULL");
-    return 0;
-  }
-  ctx->peer_identity_property_name = prop->name;
-  return 1;
-}
-
-int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) {
-  GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx));
-  return ctx->peer_identity_property_name == NULL ? 0 : 1;
-}
-
-grpc_auth_property_iterator grpc_auth_context_property_iterator(
-    const grpc_auth_context *ctx) {
-  grpc_auth_property_iterator it = empty_iterator;
-  GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx));
-  if (ctx == NULL) return it;
-  it.ctx = ctx;
-  return it;
-}
-
-const grpc_auth_property *grpc_auth_property_iterator_next(
-    grpc_auth_property_iterator *it) {
-  GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it));
-  if (it == NULL || it->ctx == NULL) return NULL;
-  while (it->index == it->ctx->properties.count) {
-    if (it->ctx->chained == NULL) return NULL;
-    it->ctx = it->ctx->chained;
-    it->index = 0;
-  }
-  if (it->name == NULL) {
-    return &it->ctx->properties.array[it->index++];
-  } else {
-    while (it->index < it->ctx->properties.count) {
-      const grpc_auth_property *prop = &it->ctx->properties.array[it->index++];
-      GPR_ASSERT(prop->name != NULL);
-      if (strcmp(it->name, prop->name) == 0) {
-        return prop;
-      }
-    }
-    /* We could not find the name, try another round. */
-    return grpc_auth_property_iterator_next(it);
-  }
-}
-
-grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
-    const grpc_auth_context *ctx, const char *name) {
-  grpc_auth_property_iterator it = empty_iterator;
-  GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)",
-                 2, (ctx, name));
-  if (ctx == NULL || name == NULL) return empty_iterator;
-  it.ctx = ctx;
-  it.name = name;
-  return it;
-}
-
-grpc_auth_property_iterator grpc_auth_context_peer_identity(
-    const grpc_auth_context *ctx) {
-  GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx));
-  if (ctx == NULL) return empty_iterator;
-  return grpc_auth_context_find_properties_by_name(
-      ctx, ctx->peer_identity_property_name);
-}
-
-static void ensure_auth_context_capacity(grpc_auth_context *ctx) {
-  if (ctx->properties.count == ctx->properties.capacity) {
-    ctx->properties.capacity =
-        GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2);
-    ctx->properties.array =
-        gpr_realloc(ctx->properties.array,
-                    ctx->properties.capacity * sizeof(grpc_auth_property));
-  }
-}
-
-void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
-                                    const char *value, size_t value_length) {
-  grpc_auth_property *prop;
-  GRPC_API_TRACE(
-      "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, "
-      "value_length=%lu)",
-      6, (ctx, name, (int)value_length, (int)value_length, value,
-          (unsigned long)value_length));
-  ensure_auth_context_capacity(ctx);
-  prop = &ctx->properties.array[ctx->properties.count++];
-  prop->name = gpr_strdup(name);
-  prop->value = gpr_malloc(value_length + 1);
-  memcpy(prop->value, value, value_length);
-  prop->value[value_length] = '\0';
-  prop->value_length = value_length;
-}
-
-void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
-                                            const char *name,
-                                            const char *value) {
-  grpc_auth_property *prop;
-  GRPC_API_TRACE(
-      "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3,
-      (ctx, name, value));
-  ensure_auth_context_capacity(ctx);
-  prop = &ctx->properties.array[ctx->properties.count++];
-  prop->name = gpr_strdup(name);
-  prop->value = gpr_strdup(value);
-  prop->value_length = strlen(value);
-}
-
-void grpc_auth_property_reset(grpc_auth_property *property) {
-  gpr_free(property->name);
-  gpr_free(property->value);
-  memset(property, 0, sizeof(grpc_auth_property));
-}
-
-static void auth_context_pointer_arg_destroy(void *p) {
-  GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg");
-}
-
-static void *auth_context_pointer_arg_copy(void *p) {
-  return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg");
-}
-
-static int auth_context_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
-
-static const grpc_arg_pointer_vtable auth_context_pointer_vtable = {
-    auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy,
-    auth_context_pointer_cmp};
-
-grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) {
-  grpc_arg arg;
-  memset(&arg, 0, sizeof(grpc_arg));
-  arg.type = GRPC_ARG_POINTER;
-  arg.key = GRPC_AUTH_CONTEXT_ARG;
-  arg.value.pointer.p = p;
-  arg.value.pointer.vtable = &auth_context_pointer_vtable;
-  return arg;
-}
-
-grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg) {
-  if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL;
-  if (arg->type != GRPC_ARG_POINTER) {
-    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
-            GRPC_AUTH_CONTEXT_ARG);
-    return NULL;
-  }
-  return arg->value.pointer.p;
-}
-
-grpc_auth_context *grpc_find_auth_context_in_args(
-    const grpc_channel_args *args) {
-  size_t i;
-  if (args == NULL) return NULL;
-  for (i = 0; i < args->num_args; i++) {
-    grpc_auth_context *p = grpc_auth_context_from_arg(&args->args[i]);
-    if (p != NULL) return p;
-  }
-  return NULL;
-}
diff --git a/src/core/lib/security/security_context.h b/src/core/lib/security/security_context.h
deleted file mode 100644
index 81161ec..0000000
--- a/src/core/lib/security/security_context.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *
- * Copyright 2015, 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_SECURITY_SECURITY_CONTEXT_H
-#define GRPC_CORE_LIB_SECURITY_SECURITY_CONTEXT_H
-
-#include "src/core/lib/iomgr/pollset.h"
-#include "src/core/lib/security/credentials.h"
-
-/* --- grpc_auth_context ---
-
-   High level authentication context object. Can optionally be chained. */
-
-/* Property names are always NULL terminated. */
-
-typedef struct {
-  grpc_auth_property *array;
-  size_t count;
-  size_t capacity;
-} grpc_auth_property_array;
-
-struct grpc_auth_context {
-  struct grpc_auth_context *chained;
-  grpc_auth_property_array properties;
-  gpr_refcount refcount;
-  const char *peer_identity_property_name;
-  grpc_pollset *pollset;
-};
-
-/* Creation. */
-grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained);
-
-/* Refcounting. */
-#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG
-#define GRPC_AUTH_CONTEXT_REF(p, r) \
-  grpc_auth_context_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_AUTH_CONTEXT_UNREF(p, r) \
-  grpc_auth_context_unref((p), __FILE__, __LINE__, (r))
-grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy,
-                                         const char *file, int line,
-                                         const char *reason);
-void grpc_auth_context_unref(grpc_auth_context *policy, const char *file,
-                             int line, const char *reason);
-#else
-#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p))
-#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p))
-grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy);
-void grpc_auth_context_unref(grpc_auth_context *policy);
-#endif
-
-void grpc_auth_property_reset(grpc_auth_property *property);
-
-/* --- grpc_client_security_context ---
-
-   Internal client-side security context. */
-
-typedef struct {
-  grpc_call_credentials *creds;
-  grpc_auth_context *auth_context;
-} grpc_client_security_context;
-
-grpc_client_security_context *grpc_client_security_context_create(void);
-void grpc_client_security_context_destroy(void *ctx);
-
-/* --- grpc_server_security_context ---
-
-   Internal server-side security context. */
-
-typedef struct {
-  grpc_auth_context *auth_context;
-} grpc_server_security_context;
-
-grpc_server_security_context *grpc_server_security_context_create(void);
-void grpc_server_security_context_destroy(void *ctx);
-
-/* --- Channel args for auth context --- */
-#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context"
-
-grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c);
-grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
-grpc_auth_context *grpc_find_auth_context_in_args(
-    const grpc_channel_args *args);
-
-#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONTEXT_H */
diff --git a/src/core/lib/security/server_auth_filter.c b/src/core/lib/security/server_auth_filter.c
deleted file mode 100644
index 8453209..0000000
--- a/src/core/lib/security/server_auth_filter.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <string.h>
-
-#include "src/core/lib/security/auth_filters.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/security_context.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-typedef struct call_data {
-  grpc_metadata_batch *recv_initial_metadata;
-  /* Closure to call when finished with the auth_on_recv hook. */
-  grpc_closure *on_done_recv;
-  /* Receive closures are chained: we inject this closure as the on_done_recv
-     up-call on transport_op, and remember to call our on_done_recv member after
-     handling it. */
-  grpc_closure auth_on_recv;
-  grpc_transport_stream_op transport_op;
-  grpc_metadata_array md;
-  const grpc_metadata *consumed_md;
-  size_t num_consumed_md;
-  grpc_auth_context *auth_context;
-} call_data;
-
-typedef struct channel_data {
-  grpc_auth_context *auth_context;
-  grpc_server_credentials *creds;
-} channel_data;
-
-static grpc_metadata_array metadata_batch_to_md_array(
-    const grpc_metadata_batch *batch) {
-  grpc_linked_mdelem *l;
-  grpc_metadata_array result;
-  grpc_metadata_array_init(&result);
-  for (l = batch->list.head; l != NULL; l = l->next) {
-    grpc_metadata *usr_md = NULL;
-    grpc_mdelem *md = l->md;
-    grpc_mdstr *key = md->key;
-    grpc_mdstr *value = md->value;
-    if (result.count == result.capacity) {
-      result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
-      result.metadata =
-          gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata));
-    }
-    usr_md = &result.metadata[result.count++];
-    usr_md->key = grpc_mdstr_as_c_string(key);
-    usr_md->value = grpc_mdstr_as_c_string(value);
-    usr_md->value_length = GPR_SLICE_LENGTH(value->slice);
-  }
-  return result;
-}
-
-static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  size_t i;
-  for (i = 0; i < calld->num_consumed_md; i++) {
-    const grpc_metadata *consumed_md = &calld->consumed_md[i];
-    /* Maybe we could do a pointer comparison but we do not have any guarantee
-       that the metadata processor used the same pointers for consumed_md in the
-       callback. */
-    if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
-        GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
-      continue;
-    }
-    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key,
-               GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
-        memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value,
-               GPR_SLICE_LENGTH(md->value->slice)) == 0) {
-      return NULL; /* Delete. */
-    }
-  }
-  return md;
-}
-
-/* called from application code */
-static void on_md_processing_done(
-    void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
-    const grpc_metadata *response_md, size_t num_response_md,
-    grpc_status_code status, const char *error_details) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  /* TODO(jboeuf): Implement support for response_md. */
-  if (response_md != NULL && num_response_md > 0) {
-    gpr_log(GPR_INFO,
-            "response_md in auth metadata processing not supported for now. "
-            "Ignoring...");
-  }
-
-  if (status == GRPC_STATUS_OK) {
-    calld->consumed_md = consumed_md;
-    calld->num_consumed_md = num_consumed_md;
-    grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md,
-                               elem);
-    grpc_metadata_array_destroy(&calld->md);
-    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1);
-  } else {
-    gpr_slice message;
-    grpc_transport_stream_op close_op;
-    memset(&close_op, 0, sizeof(close_op));
-    grpc_metadata_array_destroy(&calld->md);
-    error_details = error_details != NULL
-                        ? error_details
-                        : "Authentication metadata processing failed.";
-    message = gpr_slice_from_copied_string(error_details);
-    calld->transport_op.send_initial_metadata = NULL;
-    if (calld->transport_op.send_message != NULL) {
-      grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message);
-      calld->transport_op.send_message = NULL;
-    }
-    calld->transport_op.send_trailing_metadata = NULL;
-    grpc_transport_stream_op_add_close(&close_op, status, &message);
-    grpc_call_next_op(&exec_ctx, elem, &close_op);
-    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0);
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
-                         bool success) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  if (success) {
-    if (chand->creds->processor.process != NULL) {
-      calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata);
-      chand->creds->processor.process(
-          chand->creds->processor.state, calld->auth_context,
-          calld->md.metadata, calld->md.count, on_md_processing_done, elem);
-      return;
-    }
-  }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
-}
-
-static void set_recv_ops_md_callbacks(grpc_call_element *elem,
-                                      grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
-
-  if (op->recv_initial_metadata != NULL) {
-    /* substitute our callback for the higher callback */
-    calld->recv_initial_metadata = op->recv_initial_metadata;
-    calld->on_done_recv = op->recv_initial_metadata_ready;
-    op->recv_initial_metadata_ready = &calld->auth_on_recv;
-    calld->transport_op = *op;
-  }
-}
-
-/* Called either:
-     - in response to an API call (or similar) from above, to send something
-     - a network event (or similar) from below, to receive something
-   op contains type and call direction information, in addition to the data
-   that is being sent or received. */
-static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                    grpc_call_element *elem,
-                                    grpc_transport_stream_op *op) {
-  set_recv_ops_md_callbacks(elem, op);
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-  channel_data *chand = elem->channel_data;
-  grpc_server_security_context *server_ctx = NULL;
-
-  /* initialize members */
-  memset(calld, 0, sizeof(*calld));
-  grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
-
-  if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) {
-    args->context[GRPC_CONTEXT_SECURITY].destroy(
-        args->context[GRPC_CONTEXT_SECURITY].value);
-  }
-
-  server_ctx = grpc_server_security_context_create();
-  server_ctx->auth_context = grpc_auth_context_create(chand->auth_context);
-  calld->auth_context = server_ctx->auth_context;
-
-  args->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
-  args->context[GRPC_CONTEXT_SECURITY].destroy =
-      grpc_server_security_context_destroy;
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                              void *ignored) {}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  grpc_auth_context *auth_context =
-      grpc_find_auth_context_in_args(args->channel_args);
-  grpc_server_credentials *creds =
-      grpc_find_server_credentials_in_args(args->channel_args);
-  /* grab pointers to our data from the channel element */
-  channel_data *chand = elem->channel_data;
-
-  GPR_ASSERT(!args->is_last);
-  GPR_ASSERT(auth_context != NULL);
-  GPR_ASSERT(creds != NULL);
-
-  /* initialize members */
-  chand->auth_context =
-      GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter");
-  chand->creds = grpc_server_credentials_ref(creds);
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  /* grab pointers to our data from the channel element */
-  channel_data *chand = elem->channel_data;
-  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter");
-  grpc_server_credentials_unref(chand->creds);
-}
-
-const grpc_channel_filter grpc_server_auth_filter = {
-    auth_start_transport_op,
-    grpc_channel_next_op,
-    sizeof(call_data),
-    init_call_elem,
-    grpc_call_stack_ignore_set_pollset_or_pollset_set,
-    destroy_call_elem,
-    sizeof(channel_data),
-    init_channel_elem,
-    destroy_channel_elem,
-    grpc_call_next_get_peer,
-    "server-auth"};
diff --git a/src/core/lib/security/transport/auth_filters.h b/src/core/lib/security/transport/auth_filters.h
new file mode 100644
index 0000000..f688d4e
--- /dev/null
+++ b/src/core/lib/security/transport/auth_filters.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_TRANSPORT_AUTH_FILTERS_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+extern const grpc_channel_filter grpc_client_auth_filter;
+extern const grpc_channel_filter grpc_server_auth_filter;
+
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H */
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
new file mode 100644
index 0000000..ac504ec
--- /dev/null
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -0,0 +1,343 @@
+/*
+ *
+ * Copyright 2015, 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/security/transport/auth_filters.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/security_connector.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+#define MAX_CREDENTIALS_METADATA_COUNT 4
+
+/* We can have a per-call credentials. */
+typedef struct {
+  grpc_call_credentials *creds;
+  grpc_mdstr *host;
+  grpc_mdstr *method;
+  /* pollset{_set} bound to this call; if we need to make external
+     network requests, they should be done under a pollset added to this
+     pollset_set so that work can progress when this call wants work to progress
+  */
+  grpc_pops *pops;
+  grpc_transport_stream_op op;
+  uint8_t security_context_set;
+  grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
+  grpc_auth_metadata_context auth_md_context;
+} call_data;
+
+/* We can have a per-channel credentials. */
+typedef struct {
+  grpc_channel_security_connector *security_connector;
+  grpc_auth_context *auth_context;
+} channel_data;
+
+static void reset_auth_metadata_context(
+    grpc_auth_metadata_context *auth_md_context) {
+  if (auth_md_context->service_url != NULL) {
+    gpr_free((char *)auth_md_context->service_url);
+    auth_md_context->service_url = NULL;
+  }
+  if (auth_md_context->method_name != NULL) {
+    gpr_free((char *)auth_md_context->method_name);
+    auth_md_context->method_name = NULL;
+  }
+  GRPC_AUTH_CONTEXT_UNREF(
+      (grpc_auth_context *)auth_md_context->channel_auth_context,
+      "grpc_auth_metadata_context");
+  auth_md_context->channel_auth_context = NULL;
+}
+
+static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                            grpc_status_code status, const char *error_msg) {
+  call_data *calld = elem->call_data;
+  gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
+  grpc_transport_stream_op_add_cancellation(&calld->op, status);
+  grpc_call_next_op(exec_ctx, elem, &calld->op);
+}
+
+static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
+                                    grpc_credentials_md *md_elems,
+                                    size_t num_md,
+                                    grpc_credentials_status status) {
+  grpc_call_element *elem = (grpc_call_element *)user_data;
+  call_data *calld = elem->call_data;
+  grpc_transport_stream_op *op = &calld->op;
+  grpc_metadata_batch *mdb;
+  size_t i;
+  reset_auth_metadata_context(&calld->auth_md_context);
+  if (status != GRPC_CREDENTIALS_OK) {
+    bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
+                    "Credentials failed to get metadata.");
+    return;
+  }
+  GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
+  GPR_ASSERT(op->send_initial_metadata != NULL);
+  mdb = op->send_initial_metadata;
+  for (i = 0; i < num_md; i++) {
+    grpc_metadata_batch_add_tail(
+        mdb, &calld->md_links[i],
+        grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key),
+                                gpr_slice_ref(md_elems[i].value)));
+  }
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+void build_auth_metadata_context(grpc_security_connector *sc,
+                                 grpc_auth_context *auth_context,
+                                 call_data *calld) {
+  char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
+  char *last_slash = strrchr(service, '/');
+  char *method_name = NULL;
+  char *service_url = NULL;
+  reset_auth_metadata_context(&calld->auth_md_context);
+  if (last_slash == NULL) {
+    gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
+    service[0] = '\0';
+  } else if (last_slash == service) {
+    /* No service part in fully qualified method name: will just be "/". */
+    service[1] = '\0';
+  } else {
+    *last_slash = '\0';
+    method_name = gpr_strdup(last_slash + 1);
+  }
+  if (method_name == NULL) method_name = gpr_strdup("");
+  gpr_asprintf(&service_url, "%s://%s%s",
+               sc->url_scheme == NULL ? "" : sc->url_scheme,
+               grpc_mdstr_as_c_string(calld->host), service);
+  calld->auth_md_context.service_url = service_url;
+  calld->auth_md_context.method_name = method_name;
+  calld->auth_md_context.channel_auth_context =
+      GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
+  gpr_free(service);
+}
+
+static void send_security_metadata(grpc_exec_ctx *exec_ctx,
+                                   grpc_call_element *elem,
+                                   grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  grpc_client_security_context *ctx =
+      (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
+  grpc_call_credentials *channel_call_creds =
+      chand->security_connector->request_metadata_creds;
+  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);
+
+  if (channel_call_creds == NULL && !call_creds_has_md) {
+    /* Skip sending metadata altogether. */
+    grpc_call_next_op(exec_ctx, elem, op);
+    return;
+  }
+
+  if (channel_call_creds != NULL && call_creds_has_md) {
+    calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
+                                                          ctx->creds, NULL);
+    if (calld->creds == NULL) {
+      bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL,
+                      "Incompatible credentials set on channel and call.");
+      return;
+    }
+  } else {
+    calld->creds = grpc_call_credentials_ref(
+        call_creds_has_md ? ctx->creds : channel_call_creds);
+  }
+
+  build_auth_metadata_context(&chand->security_connector->base,
+                              chand->auth_context, calld);
+  calld->op = *op; /* Copy op (originates from the caller's stack). */
+  GPR_ASSERT(calld->pops != NULL);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, calld->creds, calld->pops, calld->auth_md_context,
+      on_credentials_metadata, elem);
+}
+
+static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
+                            grpc_security_status status) {
+  grpc_call_element *elem = (grpc_call_element *)user_data;
+  call_data *calld = elem->call_data;
+
+  if (status == GRPC_SECURITY_OK) {
+    send_security_metadata(exec_ctx, elem, &calld->op);
+  } else {
+    char *error_msg;
+    gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
+                 grpc_mdstr_as_c_string(calld->host));
+    bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg);
+    gpr_free(error_msg);
+  }
+}
+
+/* Called either:
+     - in response to an API call (or similar) from above, to send something
+     - a network event (or similar) from below, to receive something
+   op contains type and call direction information, in addition to the data
+   that is being sent or received. */
+static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                    grpc_call_element *elem,
+                                    grpc_transport_stream_op *op) {
+  /* grab pointers to our data from the call element */
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  grpc_linked_mdelem *l;
+  grpc_client_security_context *sec_ctx = NULL;
+
+  if (calld->security_context_set == 0 &&
+      op->cancel_with_status == GRPC_STATUS_OK) {
+    calld->security_context_set = 1;
+    GPR_ASSERT(op->context);
+    if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
+      op->context[GRPC_CONTEXT_SECURITY].value =
+          grpc_client_security_context_create();
+      op->context[GRPC_CONTEXT_SECURITY].destroy =
+          grpc_client_security_context_destroy;
+    }
+    sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
+    GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
+    sec_ctx->auth_context =
+        GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter");
+  }
+
+  if (op->send_initial_metadata != NULL) {
+    for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) {
+      grpc_mdelem *md = l->md;
+      /* Pointer comparison is OK for md_elems created from the same context.
+       */
+      if (md->key == GRPC_MDSTR_AUTHORITY) {
+        if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
+        calld->host = GRPC_MDSTR_REF(md->value);
+      } else if (md->key == GRPC_MDSTR_PATH) {
+        if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
+        calld->method = GRPC_MDSTR_REF(md->value);
+      }
+    }
+    if (calld->host != NULL) {
+      const char *call_host = grpc_mdstr_as_c_string(calld->host);
+      calld->op = *op; /* Copy op (originates from the caller's stack). */
+      grpc_channel_security_connector_check_call_host(
+          exec_ctx, chand->security_connector, call_host, chand->auth_context,
+          on_host_checked, elem);
+      return; /* early exit */
+    }
+  }
+
+  /* pass control down the stack */
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+/* Constructor for call_data */
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_call_element_args *args) {
+  call_data *calld = elem->call_data;
+  memset(calld, 0, sizeof(*calld));
+}
+
+static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
+                                       grpc_call_element *elem,
+                                       grpc_pops *pops) {
+  call_data *calld = elem->call_data;
+  calld->pops = pops;
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                              void *ignored) {
+  call_data *calld = elem->call_data;
+  grpc_call_credentials_unref(calld->creds);
+  if (calld->host != NULL) {
+    GRPC_MDSTR_UNREF(calld->host);
+  }
+  if (calld->method != NULL) {
+    GRPC_MDSTR_UNREF(calld->method);
+  }
+  reset_auth_metadata_context(&calld->auth_md_context);
+}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  grpc_security_connector *sc =
+      grpc_find_security_connector_in_args(args->channel_args);
+  grpc_auth_context *auth_context =
+      grpc_find_auth_context_in_args(args->channel_args);
+
+  /* grab pointers to our data from the channel element */
+  channel_data *chand = elem->channel_data;
+
+  /* The first and the last filters tend to be implemented differently to
+     handle the case that there's no 'next' filter to call on the up or down
+     path */
+  GPR_ASSERT(!args->is_last);
+  GPR_ASSERT(sc != NULL);
+  GPR_ASSERT(auth_context != NULL);
+
+  /* initialize members */
+  chand->security_connector =
+      (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
+          sc, "client_auth_filter");
+  chand->auth_context =
+      GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
+}
+
+/* Destructor for channel data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  /* grab pointers to our data from the channel element */
+  channel_data *chand = elem->channel_data;
+  grpc_channel_security_connector *sc = chand->security_connector;
+  if (sc != NULL) {
+    GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
+  }
+  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
+}
+
+const grpc_channel_filter grpc_client_auth_filter = {auth_start_transport_op,
+                                                     grpc_channel_next_op,
+                                                     sizeof(call_data),
+                                                     init_call_elem,
+                                                     set_pollset_or_pollset_set,
+                                                     destroy_call_elem,
+                                                     sizeof(channel_data),
+                                                     init_channel_elem,
+                                                     destroy_channel_elem,
+                                                     grpc_call_next_get_peer,
+                                                     "client-auth"};
diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c
new file mode 100644
index 0000000..6561f4b
--- /dev/null
+++ b/src/core/lib/security/transport/handshake.c
@@ -0,0 +1,336 @@
+/*
+ *
+ * Copyright 2015, 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/security/transport/handshake.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/transport/secure_endpoint.h"
+
+#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
+
+typedef struct {
+  grpc_security_connector *connector;
+  tsi_handshaker *handshaker;
+  bool is_client_side;
+  unsigned char *handshake_buffer;
+  size_t handshake_buffer_size;
+  grpc_endpoint *wrapped_endpoint;
+  grpc_endpoint *secure_endpoint;
+  gpr_slice_buffer left_overs;
+  gpr_slice_buffer incoming;
+  gpr_slice_buffer outgoing;
+  grpc_security_handshake_done_cb cb;
+  void *user_data;
+  grpc_closure on_handshake_data_sent_to_peer;
+  grpc_closure on_handshake_data_received_from_peer;
+  grpc_auth_context *auth_context;
+} grpc_security_handshake;
+
+static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
+                                                 void *setup, bool success);
+
+static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
+                                           bool success);
+
+static void security_connector_remove_handshake(grpc_security_handshake *h) {
+  GPR_ASSERT(!h->is_client_side);
+  grpc_security_connector_handshake_list *node;
+  grpc_security_connector_handshake_list *tmp;
+  grpc_server_security_connector *sc =
+      (grpc_server_security_connector *)h->connector;
+  gpr_mu_lock(&sc->mu);
+  node = sc->handshaking_handshakes;
+  if (node && node->handshake == h) {
+    sc->handshaking_handshakes = node->next;
+    gpr_free(node);
+    gpr_mu_unlock(&sc->mu);
+    return;
+  }
+  while (node) {
+    if (node->next->handshake == h) {
+      tmp = node->next;
+      node->next = node->next->next;
+      gpr_free(tmp);
+      gpr_mu_unlock(&sc->mu);
+      return;
+    }
+    node = node->next;
+  }
+  gpr_mu_unlock(&sc->mu);
+}
+
+static void security_handshake_done(grpc_exec_ctx *exec_ctx,
+                                    grpc_security_handshake *h,
+                                    int is_success) {
+  if (!h->is_client_side) {
+    security_connector_remove_handshake(h);
+  }
+  if (is_success) {
+    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
+          h->auth_context);
+  } else {
+    if (h->secure_endpoint != NULL) {
+      grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
+      grpc_endpoint_destroy(exec_ctx, h->secure_endpoint);
+    } else {
+      grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
+    }
+    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+  }
+  if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
+  if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
+  gpr_slice_buffer_destroy(&h->left_overs);
+  gpr_slice_buffer_destroy(&h->outgoing);
+  gpr_slice_buffer_destroy(&h->incoming);
+  GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
+  GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
+  gpr_free(h);
+}
+
+static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
+                            grpc_security_status status,
+                            grpc_auth_context *auth_context) {
+  grpc_security_handshake *h = user_data;
+  tsi_frame_protector *protector;
+  tsi_result result;
+  if (status != GRPC_SECURITY_OK) {
+    gpr_log(GPR_ERROR, "Error checking peer.");
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+  h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
+  result =
+      tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.",
+            tsi_result_to_string(result));
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+  h->secure_endpoint =
+      grpc_secure_endpoint_create(protector, h->wrapped_endpoint,
+                                  h->left_overs.slices, h->left_overs.count);
+  h->left_overs.count = 0;
+  h->left_overs.length = 0;
+  security_handshake_done(exec_ctx, h, 1);
+  return;
+}
+
+static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
+  tsi_peer peer;
+  tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
+
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Peer extraction failed with error %s",
+            tsi_result_to_string(result));
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+  grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
+                                     on_peer_checked, h);
+}
+
+static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,
+                                         grpc_security_handshake *h) {
+  size_t offset = 0;
+  tsi_result result = TSI_OK;
+  gpr_slice to_send;
+
+  do {
+    size_t to_send_size = h->handshake_buffer_size - offset;
+    result = tsi_handshaker_get_bytes_to_send_to_peer(
+        h->handshaker, h->handshake_buffer + offset, &to_send_size);
+    offset += to_send_size;
+    if (result == TSI_INCOMPLETE_DATA) {
+      h->handshake_buffer_size *= 2;
+      h->handshake_buffer =
+          gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
+    }
+  } while (result == TSI_INCOMPLETE_DATA);
+
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshake failed with error %s",
+            tsi_result_to_string(result));
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+
+  to_send =
+      gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
+  gpr_slice_buffer_reset_and_unref(&h->outgoing);
+  gpr_slice_buffer_add(&h->outgoing, to_send);
+  /* TODO(klempner,jboeuf): This should probably use the client setup
+     deadline */
+  grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing,
+                      &h->on_handshake_data_sent_to_peer);
+}
+
+static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
+                                                 void *handshake,
+                                                 bool success) {
+  grpc_security_handshake *h = handshake;
+  size_t consumed_slice_size = 0;
+  tsi_result result = TSI_OK;
+  size_t i;
+  size_t num_left_overs;
+  int has_left_overs_in_current_slice = 0;
+
+  if (!success) {
+    gpr_log(GPR_ERROR, "Read failed.");
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+
+  for (i = 0; i < h->incoming.count; i++) {
+    consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
+    result = tsi_handshaker_process_bytes_from_peer(
+        h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
+        &consumed_slice_size);
+    if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
+  }
+
+  if (tsi_handshaker_is_in_progress(h->handshaker)) {
+    /* We may need more data. */
+    if (result == TSI_INCOMPLETE_DATA) {
+      grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
+                         &h->on_handshake_data_received_from_peer);
+      return;
+    } else {
+      send_handshake_bytes_to_peer(exec_ctx, h);
+      return;
+    }
+  }
+
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshake failed with error %s",
+            tsi_result_to_string(result));
+    security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+
+  /* Handshake is done and successful this point. */
+  has_left_overs_in_current_slice =
+      (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
+  num_left_overs =
+      (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
+  if (num_left_overs == 0) {
+    check_peer(exec_ctx, h);
+    return;
+  }
+
+  /* Put the leftovers in our buffer (ownership transfered). */
+  if (has_left_overs_in_current_slice) {
+    gpr_slice_buffer_add(
+        &h->left_overs,
+        gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
+    gpr_slice_unref(
+        h->incoming.slices[i]); /* split_tail above increments refcount. */
+  }
+  gpr_slice_buffer_addn(
+      &h->left_overs, &h->incoming.slices[i + 1],
+      num_left_overs - (size_t)has_left_overs_in_current_slice);
+  check_peer(exec_ctx, h);
+}
+
+/* If handshake is NULL, the handshake is done. */
+static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
+                                           void *handshake, bool success) {
+  grpc_security_handshake *h = handshake;
+
+  /* Make sure that write is OK. */
+  if (!success) {
+    gpr_log(GPR_ERROR, "Write failed.");
+    if (handshake != NULL) security_handshake_done(exec_ctx, h, 0);
+    return;
+  }
+
+  /* We may be done. */
+  if (tsi_handshaker_is_in_progress(h->handshaker)) {
+    /* TODO(klempner,jboeuf): This should probably use the client setup
+       deadline */
+    grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
+                       &h->on_handshake_data_received_from_peer);
+  } else {
+    check_peer(exec_ctx, h);
+  }
+}
+
+void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
+                                tsi_handshaker *handshaker,
+                                grpc_security_connector *connector,
+                                bool is_client_side,
+                                grpc_endpoint *nonsecure_endpoint,
+                                grpc_security_handshake_done_cb cb,
+                                void *user_data) {
+  grpc_security_connector_handshake_list *handshake_node;
+  grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
+  memset(h, 0, sizeof(grpc_security_handshake));
+  h->handshaker = handshaker;
+  h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
+  h->is_client_side = is_client_side;
+  h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
+  h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
+  h->wrapped_endpoint = nonsecure_endpoint;
+  h->user_data = user_data;
+  h->cb = cb;
+  grpc_closure_init(&h->on_handshake_data_sent_to_peer,
+                    on_handshake_data_sent_to_peer, h);
+  grpc_closure_init(&h->on_handshake_data_received_from_peer,
+                    on_handshake_data_received_from_peer, h);
+  gpr_slice_buffer_init(&h->left_overs);
+  gpr_slice_buffer_init(&h->outgoing);
+  gpr_slice_buffer_init(&h->incoming);
+  if (!is_client_side) {
+    grpc_server_security_connector *server_connector =
+        (grpc_server_security_connector *)connector;
+    handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
+    handshake_node->handshake = h;
+    gpr_mu_lock(&server_connector->mu);
+    handshake_node->next = server_connector->handshaking_handshakes;
+    server_connector->handshaking_handshakes = handshake_node;
+    gpr_mu_unlock(&server_connector->mu);
+  }
+  send_handshake_bytes_to_peer(exec_ctx, h);
+}
+
+void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
+                                      void *handshake) {
+  grpc_security_handshake *h = handshake;
+  grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
+}
diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/handshake.h
new file mode 100644
index 0000000..6ed850b
--- /dev/null
+++ b/src/core/lib/security/transport/handshake.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_TRANSPORT_HANDSHAKE_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/security/transport/security_connector.h"
+
+/* Calls the callback upon completion. Takes owership of handshaker. */
+void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
+                                tsi_handshaker *handshaker,
+                                grpc_security_connector *connector,
+                                bool is_client_side,
+                                grpc_endpoint *nonsecure_endpoint,
+                                grpc_security_handshake_done_cb cb,
+                                void *user_data);
+
+void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
+
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H */
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
new file mode 100644
index 0000000..4438c8e
--- /dev/null
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -0,0 +1,384 @@
+/*
+ *
+ * Copyright 2015, 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/security/transport/secure_endpoint.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/sync.h>
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+#define STAGING_BUFFER_SIZE 8192
+
+typedef struct {
+  grpc_endpoint base;
+  grpc_endpoint *wrapped_ep;
+  struct tsi_frame_protector *protector;
+  gpr_mu protector_mu;
+  /* saved upper level callbacks and user_data. */
+  grpc_closure *read_cb;
+  grpc_closure *write_cb;
+  grpc_closure on_read;
+  gpr_slice_buffer *read_buffer;
+  gpr_slice_buffer source_buffer;
+  /* saved handshaker leftover data to unprotect. */
+  gpr_slice_buffer leftover_bytes;
+  /* buffers for read and write */
+  gpr_slice read_staging_buffer;
+
+  gpr_slice write_staging_buffer;
+  gpr_slice_buffer output_buffer;
+
+  gpr_refcount ref;
+} secure_endpoint;
+
+int grpc_trace_secure_endpoint = 0;
+
+static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
+  secure_endpoint *ep = secure_ep;
+  grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep);
+  tsi_frame_protector_destroy(ep->protector);
+  gpr_slice_buffer_destroy(&ep->leftover_bytes);
+  gpr_slice_unref(ep->read_staging_buffer);
+  gpr_slice_unref(ep->write_staging_buffer);
+  gpr_slice_buffer_destroy(&ep->output_buffer);
+  gpr_slice_buffer_destroy(&ep->source_buffer);
+  gpr_mu_destroy(&ep->protector_mu);
+  gpr_free(ep);
+}
+
+/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/
+#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
+#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
+  secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__)
+#define SECURE_ENDPOINT_REF(ep, reason) \
+  secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
+static void secure_endpoint_unref(secure_endpoint *ep,
+                                  grpc_closure_list *closure_list,
+                                  const char *reason, const char *file,
+                                  int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d",
+          ep, reason, ep->ref.count, ep->ref.count - 1);
+  if (gpr_unref(&ep->ref)) {
+    destroy(exec_ctx, ep);
+  }
+}
+
+static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
+                                const char *file, int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP   ref %p : %s %d -> %d",
+          ep, reason, ep->ref.count, ep->ref.count + 1);
+  gpr_ref(&ep->ref);
+}
+#else
+#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
+  secure_endpoint_unref((exec_ctx), (ep))
+#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep))
+static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx,
+                                  secure_endpoint *ep) {
+  if (gpr_unref(&ep->ref)) {
+    destroy(exec_ctx, ep);
+  }
+}
+
+static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
+#endif
+
+static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur,
+                                      uint8_t **end) {
+  gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer);
+  ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
+  *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
+  *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
+}
+
+static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
+                         bool success) {
+  if (grpc_trace_secure_endpoint) {
+    size_t i;
+    for (i = 0; i < ep->read_buffer->count; i++) {
+      char *data = gpr_dump_slice(ep->read_buffer->slices[i],
+                                  GPR_DUMP_HEX | GPR_DUMP_ASCII);
+      gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
+      gpr_free(data);
+    }
+  }
+  ep->read_buffer = NULL;
+  grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success, NULL);
+  SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
+}
+
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+  unsigned i;
+  uint8_t keep_looping = 0;
+  tsi_result result = TSI_OK;
+  secure_endpoint *ep = (secure_endpoint *)user_data;
+  uint8_t *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
+  uint8_t *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
+
+  if (!success) {
+    gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+    call_read_cb(exec_ctx, ep, 0);
+    return;
+  }
+
+  /* TODO(yangg) check error, maybe bail out early */
+  for (i = 0; i < ep->source_buffer.count; i++) {
+    gpr_slice encrypted = ep->source_buffer.slices[i];
+    uint8_t *message_bytes = GPR_SLICE_START_PTR(encrypted);
+    size_t message_size = GPR_SLICE_LENGTH(encrypted);
+
+    while (message_size > 0 || keep_looping) {
+      size_t unprotected_buffer_size_written = (size_t)(end - cur);
+      size_t processed_message_size = message_size;
+      gpr_mu_lock(&ep->protector_mu);
+      result = tsi_frame_protector_unprotect(ep->protector, message_bytes,
+                                             &processed_message_size, cur,
+                                             &unprotected_buffer_size_written);
+      gpr_mu_unlock(&ep->protector_mu);
+      if (result != TSI_OK) {
+        gpr_log(GPR_ERROR, "Decryption error: %s",
+                tsi_result_to_string(result));
+        break;
+      }
+      message_bytes += processed_message_size;
+      message_size -= processed_message_size;
+      cur += unprotected_buffer_size_written;
+
+      if (cur == end) {
+        flush_read_staging_buffer(ep, &cur, &end);
+        /* Force to enter the loop again to extract buffered bytes in protector.
+           The bytes could be buffered because of running out of staging_buffer.
+           If this happens at the end of all slices, doing another unprotect
+           avoids leaving data in the protector. */
+        keep_looping = 1;
+      } else if (unprotected_buffer_size_written > 0) {
+        keep_looping = 1;
+      } else {
+        keep_looping = 0;
+      }
+    }
+    if (result != TSI_OK) break;
+  }
+
+  if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) {
+    gpr_slice_buffer_add(
+        ep->read_buffer,
+        gpr_slice_split_head(
+            &ep->read_staging_buffer,
+            (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer))));
+  }
+
+  /* TODO(yangg) experiment with moving this block after read_cb to see if it
+     helps latency */
+  gpr_slice_buffer_reset_and_unref(&ep->source_buffer);
+
+  if (result != TSI_OK) {
+    gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+    call_read_cb(exec_ctx, ep, 0);
+    return;
+  }
+
+  call_read_cb(exec_ctx, ep, 1);
+}
+
+static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
+                          gpr_slice_buffer *slices, grpc_closure *cb) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  ep->read_cb = cb;
+  ep->read_buffer = slices;
+  gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+
+  SECURE_ENDPOINT_REF(ep, "read");
+  if (ep->leftover_bytes.count) {
+    gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
+    GPR_ASSERT(ep->leftover_bytes.count == 0);
+    on_read(exec_ctx, ep, 1);
+    return;
+  }
+
+  grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer,
+                     &ep->on_read);
+}
+
+static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur,
+                                       uint8_t **end) {
+  gpr_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer);
+  ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
+  *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
+  *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
+}
+
+static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
+                           gpr_slice_buffer *slices, grpc_closure *cb) {
+  unsigned i;
+  tsi_result result = TSI_OK;
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  uint8_t *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
+  uint8_t *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
+
+  gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
+
+  if (grpc_trace_secure_endpoint) {
+    for (i = 0; i < slices->count; i++) {
+      char *data =
+          gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+      gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
+      gpr_free(data);
+    }
+  }
+
+  for (i = 0; i < slices->count; i++) {
+    gpr_slice plain = slices->slices[i];
+    uint8_t *message_bytes = GPR_SLICE_START_PTR(plain);
+    size_t message_size = GPR_SLICE_LENGTH(plain);
+    while (message_size > 0) {
+      size_t protected_buffer_size_to_send = (size_t)(end - cur);
+      size_t processed_message_size = message_size;
+      gpr_mu_lock(&ep->protector_mu);
+      result = tsi_frame_protector_protect(ep->protector, message_bytes,
+                                           &processed_message_size, cur,
+                                           &protected_buffer_size_to_send);
+      gpr_mu_unlock(&ep->protector_mu);
+      if (result != TSI_OK) {
+        gpr_log(GPR_ERROR, "Encryption error: %s",
+                tsi_result_to_string(result));
+        break;
+      }
+      message_bytes += processed_message_size;
+      message_size -= processed_message_size;
+      cur += protected_buffer_size_to_send;
+
+      if (cur == end) {
+        flush_write_staging_buffer(ep, &cur, &end);
+      }
+    }
+    if (result != TSI_OK) break;
+  }
+  if (result == TSI_OK) {
+    size_t still_pending_size;
+    do {
+      size_t protected_buffer_size_to_send = (size_t)(end - cur);
+      gpr_mu_lock(&ep->protector_mu);
+      result = tsi_frame_protector_protect_flush(ep->protector, cur,
+                                                 &protected_buffer_size_to_send,
+                                                 &still_pending_size);
+      gpr_mu_unlock(&ep->protector_mu);
+      if (result != TSI_OK) break;
+      cur += protected_buffer_size_to_send;
+      if (cur == end) {
+        flush_write_staging_buffer(ep, &cur, &end);
+      }
+    } while (still_pending_size > 0);
+    if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) {
+      gpr_slice_buffer_add(
+          &ep->output_buffer,
+          gpr_slice_split_head(
+              &ep->write_staging_buffer,
+              (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer))));
+    }
+  }
+
+  if (result != TSI_OK) {
+    /* TODO(yangg) do different things according to the error type? */
+    gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
+    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    return;
+  }
+
+  grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb);
+}
+
+static void endpoint_shutdown(grpc_exec_ctx *exec_ctx,
+                              grpc_endpoint *secure_ep) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep);
+}
+
+static void endpoint_destroy(grpc_exec_ctx *exec_ctx,
+                             grpc_endpoint *secure_ep) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy");
+}
+
+static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx,
+                                    grpc_endpoint *secure_ep,
+                                    grpc_pollset *pollset) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset);
+}
+
+static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
+                                        grpc_endpoint *secure_ep,
+                                        grpc_pollset_set *pollset_set) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set);
+}
+
+static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  return grpc_endpoint_get_peer(ep->wrapped_ep);
+}
+
+static const grpc_endpoint_vtable vtable = {
+    endpoint_read,           endpoint_write,
+    endpoint_add_to_pollset, endpoint_add_to_pollset_set,
+    endpoint_shutdown,       endpoint_destroy,
+    endpoint_get_peer};
+
+grpc_endpoint *grpc_secure_endpoint_create(
+    struct tsi_frame_protector *protector, grpc_endpoint *transport,
+    gpr_slice *leftover_slices, size_t leftover_nslices) {
+  size_t i;
+  secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint));
+  ep->base.vtable = &vtable;
+  ep->wrapped_ep = transport;
+  ep->protector = protector;
+  gpr_slice_buffer_init(&ep->leftover_bytes);
+  for (i = 0; i < leftover_nslices; i++) {
+    gpr_slice_buffer_add(&ep->leftover_bytes,
+                         gpr_slice_ref(leftover_slices[i]));
+  }
+  ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
+  ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
+  gpr_slice_buffer_init(&ep->output_buffer);
+  gpr_slice_buffer_init(&ep->source_buffer);
+  ep->read_buffer = NULL;
+  grpc_closure_init(&ep->on_read, on_read, ep);
+  gpr_mu_init(&ep->protector_mu);
+  gpr_ref_init(&ep->ref, 1);
+  return &ep->base;
+}
diff --git a/src/core/lib/security/transport/secure_endpoint.h b/src/core/lib/security/transport/secure_endpoint.h
new file mode 100644
index 0000000..d00075b
--- /dev/null
+++ b/src/core/lib/security/transport/secure_endpoint.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_TRANSPORT_SECURE_ENDPOINT_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H
+
+#include <grpc/support/slice.h>
+#include "src/core/lib/iomgr/endpoint.h"
+
+struct tsi_frame_protector;
+
+extern int grpc_trace_secure_endpoint;
+
+/* Takes ownership of protector and to_wrap, and refs leftover_slices. */
+grpc_endpoint *grpc_secure_endpoint_create(
+    struct tsi_frame_protector *protector, grpc_endpoint *to_wrap,
+    gpr_slice *leftover_slices, size_t leftover_nslices);
+
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H */
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
new file mode 100644
index 0000000..72173e7
--- /dev/null
+++ b/src/core/lib/security/transport/security_connector.c
@@ -0,0 +1,838 @@
+/*
+ *
+ * Copyright 2015, 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/security/transport/security_connector.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/transport/chttp2/alpn/alpn.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/handshake.h"
+#include "src/core/lib/security/transport/secure_endpoint.h"
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/tsi/fake_transport_security.h"
+#include "src/core/lib/tsi/ssl_transport_security.h"
+
+/* -- Constants. -- */
+
+#ifndef INSTALL_PREFIX
+static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
+#else
+static const char *installed_roots_path =
+    INSTALL_PREFIX "/share/grpc/roots.pem";
+#endif
+
+/* -- Overridden default roots. -- */
+
+static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL;
+
+void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) {
+  ssl_roots_override_cb = cb;
+}
+
+/* -- Cipher suites. -- */
+
+/* Defines the cipher suites that we accept by default. All these cipher suites
+   are compliant with HTTP2. */
+#define GRPC_SSL_CIPHER_SUITES                                            \
+  "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \
+  "SHA384:ECDHE-RSA-AES256-GCM-SHA384"
+
+static gpr_once cipher_suites_once = GPR_ONCE_INIT;
+static const char *cipher_suites = NULL;
+
+static void init_cipher_suites(void) {
+  char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES");
+  cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES;
+}
+
+static const char *ssl_cipher_suites(void) {
+  gpr_once_init(&cipher_suites_once, init_cipher_suites);
+  return cipher_suites;
+}
+
+/* -- Common methods. -- */
+
+/* Returns the first property with that name. */
+const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
+                                                       const char *name) {
+  size_t i;
+  if (peer == NULL) return NULL;
+  for (i = 0; i < peer->property_count; i++) {
+    const tsi_peer_property *property = &peer->properties[i];
+    if (name == NULL && property->name == NULL) {
+      return property;
+    }
+    if (name != NULL && property->name != NULL &&
+        strcmp(property->name, name) == 0) {
+      return property;
+    }
+  }
+  return NULL;
+}
+
+void grpc_server_security_connector_shutdown(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) {
+  grpc_security_connector_handshake_list *tmp;
+  gpr_mu_lock(&connector->mu);
+  while (connector->handshaking_handshakes) {
+    tmp = connector->handshaking_handshakes;
+    grpc_security_handshake_shutdown(
+        exec_ctx, connector->handshaking_handshakes->handshake);
+    connector->handshaking_handshakes = tmp->next;
+    gpr_free(tmp);
+  }
+  gpr_mu_unlock(&connector->mu);
+}
+
+void grpc_channel_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
+    void *user_data) {
+  if (sc == NULL || nonsecure_endpoint == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+  } else {
+    sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
+  }
+}
+
+void grpc_server_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+    grpc_security_handshake_done_cb cb, void *user_data) {
+  if (sc == NULL || nonsecure_endpoint == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+  } else {
+    sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data);
+  }
+}
+
+void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
+                                        grpc_security_connector *sc,
+                                        tsi_peer peer,
+                                        grpc_security_peer_check_cb cb,
+                                        void *user_data) {
+  if (sc == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
+    tsi_peer_destruct(&peer);
+  } else {
+    sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data);
+  }
+}
+
+void grpc_channel_security_connector_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    const char *host, grpc_auth_context *auth_context,
+    grpc_security_call_host_check_cb cb, void *user_data) {
+  if (sc == NULL || sc->check_call_host == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR);
+  } else {
+    sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data);
+  }
+}
+
+#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
+grpc_security_connector *grpc_security_connector_ref(
+    grpc_security_connector *sc, const char *file, int line,
+    const char *reason) {
+  if (sc == NULL) return NULL;
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "SECURITY_CONNECTOR:%p   ref %d -> %d %s", sc,
+          (int)sc->refcount.count, (int)sc->refcount.count + 1, reason);
+#else
+grpc_security_connector *grpc_security_connector_ref(
+    grpc_security_connector *sc) {
+  if (sc == NULL) return NULL;
+#endif
+  gpr_ref(&sc->refcount);
+  return sc;
+}
+
+#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
+void grpc_security_connector_unref(grpc_security_connector *sc,
+                                   const char *file, int line,
+                                   const char *reason) {
+  if (sc == NULL) return;
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc,
+          (int)sc->refcount.count, (int)sc->refcount.count - 1, reason);
+#else
+void grpc_security_connector_unref(grpc_security_connector *sc) {
+  if (sc == NULL) return;
+#endif
+  if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc);
+}
+
+static void connector_pointer_arg_destroy(void *p) {
+  GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg");
+}
+
+static void *connector_pointer_arg_copy(void *p) {
+  return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg");
+}
+
+static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
+
+static const grpc_arg_pointer_vtable connector_pointer_vtable = {
+    connector_pointer_arg_copy, connector_pointer_arg_destroy,
+    connector_pointer_cmp};
+
+grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
+  grpc_arg result;
+  result.type = GRPC_ARG_POINTER;
+  result.key = GRPC_SECURITY_CONNECTOR_ARG;
+  result.value.pointer.vtable = &connector_pointer_vtable;
+  result.value.pointer.p = sc;
+  return result;
+}
+
+grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) {
+  if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL;
+  if (arg->type != GRPC_ARG_POINTER) {
+    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+            GRPC_SECURITY_CONNECTOR_ARG);
+    return NULL;
+  }
+  return arg->value.pointer.p;
+}
+
+grpc_security_connector *grpc_find_security_connector_in_args(
+    const grpc_channel_args *args) {
+  size_t i;
+  if (args == NULL) return NULL;
+  for (i = 0; i < args->num_args; i++) {
+    grpc_security_connector *sc =
+        grpc_security_connector_from_arg(&args->args[i]);
+    if (sc != NULL) return sc;
+  }
+  return NULL;
+}
+
+/* -- Fake implementation. -- */
+
+static void fake_channel_destroy(grpc_security_connector *sc) {
+  grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
+  grpc_call_credentials_unref(c->request_metadata_creds);
+  gpr_free(sc);
+}
+
+static void fake_server_destroy(grpc_security_connector *sc) {
+  grpc_server_security_connector *c = (grpc_server_security_connector *)sc;
+  gpr_mu_destroy(&c->mu);
+  gpr_free(sc);
+}
+
+static void fake_check_peer(grpc_exec_ctx *exec_ctx,
+                            grpc_security_connector *sc, tsi_peer peer,
+                            grpc_security_peer_check_cb cb, void *user_data) {
+  const char *prop_name;
+  grpc_security_status status = GRPC_SECURITY_OK;
+  grpc_auth_context *auth_context = NULL;
+  if (peer.property_count != 1) {
+    gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
+    status = GRPC_SECURITY_ERROR;
+    goto end;
+  }
+  prop_name = peer.properties[0].name;
+  if (prop_name == NULL ||
+      strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) {
+    gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.",
+            prop_name == NULL ? "<EMPTY>" : prop_name);
+    status = GRPC_SECURITY_ERROR;
+    goto end;
+  }
+  if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE,
+              peer.properties[0].value.length)) {
+    gpr_log(GPR_ERROR, "Invalid value for cert type property.");
+    status = GRPC_SECURITY_ERROR;
+    goto end;
+  }
+  auth_context = grpc_auth_context_create(NULL);
+  grpc_auth_context_add_cstring_property(
+      auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
+      GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
+
+end:
+  cb(exec_ctx, user_data, status, auth_context);
+  grpc_auth_context_unref(auth_context);
+  tsi_peer_destruct(&peer);
+}
+
+static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+                                         grpc_channel_security_connector *sc,
+                                         const char *host,
+                                         grpc_auth_context *auth_context,
+                                         grpc_security_call_host_check_cb cb,
+                                         void *user_data) {
+  cb(exec_ctx, user_data, GRPC_SECURITY_OK);
+}
+
+static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
+                                      grpc_channel_security_connector *sc,
+                                      grpc_endpoint *nonsecure_endpoint,
+                                      grpc_security_handshake_done_cb cb,
+                                      void *user_data) {
+  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
+                             true, nonsecure_endpoint, cb, user_data);
+}
+
+static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
+                                     grpc_server_security_connector *sc,
+                                     grpc_tcp_server_acceptor *acceptor,
+                                     grpc_endpoint *nonsecure_endpoint,
+                                     grpc_security_handshake_done_cb cb,
+                                     void *user_data) {
+  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
+                             false, nonsecure_endpoint, cb, user_data);
+}
+
+static grpc_security_connector_vtable fake_channel_vtable = {
+    fake_channel_destroy, fake_check_peer};
+
+static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy,
+                                                            fake_check_peer};
+
+grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
+    grpc_call_credentials *request_metadata_creds) {
+  grpc_channel_security_connector *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  gpr_ref_init(&c->base.refcount, 1);
+  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+  c->base.vtable = &fake_channel_vtable;
+  c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds);
+  c->check_call_host = fake_channel_check_call_host;
+  c->do_handshake = fake_channel_do_handshake;
+  return c;
+}
+
+grpc_server_security_connector *grpc_fake_server_security_connector_create(
+    void) {
+  grpc_server_security_connector *c =
+      gpr_malloc(sizeof(grpc_server_security_connector));
+  memset(c, 0, sizeof(*c));
+  gpr_ref_init(&c->base.refcount, 1);
+  c->base.vtable = &fake_server_vtable;
+  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+  c->do_handshake = fake_server_do_handshake;
+  gpr_mu_init(&c->mu);
+  return c;
+}
+
+/* --- Ssl implementation. --- */
+
+typedef struct {
+  grpc_channel_security_connector base;
+  tsi_ssl_handshaker_factory *handshaker_factory;
+  char *target_name;
+  char *overridden_target_name;
+} grpc_ssl_channel_security_connector;
+
+typedef struct {
+  grpc_server_security_connector base;
+  tsi_ssl_handshaker_factory *handshaker_factory;
+} grpc_ssl_server_security_connector;
+
+static void ssl_channel_destroy(grpc_security_connector *sc) {
+  grpc_ssl_channel_security_connector *c =
+      (grpc_ssl_channel_security_connector *)sc;
+  grpc_call_credentials_unref(c->base.request_metadata_creds);
+  if (c->handshaker_factory != NULL) {
+    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+  }
+  if (c->target_name != NULL) gpr_free(c->target_name);
+  if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
+  gpr_free(sc);
+}
+
+static void ssl_server_destroy(grpc_security_connector *sc) {
+  grpc_ssl_server_security_connector *c =
+      (grpc_ssl_server_security_connector *)sc;
+
+  if (c->handshaker_factory != NULL) {
+    tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+  }
+  gpr_mu_destroy(&c->base.mu);
+  gpr_free(sc);
+}
+
+static grpc_security_status ssl_create_handshaker(
+    tsi_ssl_handshaker_factory *handshaker_factory, bool is_client,
+    const char *peer_name, tsi_handshaker **handshaker) {
+  tsi_result result = TSI_OK;
+  if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
+  result = tsi_ssl_handshaker_factory_create_handshaker(
+      handshaker_factory, is_client ? peer_name : NULL, handshaker);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
+            tsi_result_to_string(result));
+    return GRPC_SECURITY_ERROR;
+  }
+  return GRPC_SECURITY_OK;
+}
+
+static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
+                                     grpc_channel_security_connector *sc,
+                                     grpc_endpoint *nonsecure_endpoint,
+                                     grpc_security_handshake_done_cb cb,
+                                     void *user_data) {
+  grpc_ssl_channel_security_connector *c =
+      (grpc_ssl_channel_security_connector *)sc;
+  tsi_handshaker *handshaker;
+  grpc_security_status status = ssl_create_handshaker(
+      c->handshaker_factory, true,
+      c->overridden_target_name != NULL ? c->overridden_target_name
+                                        : c->target_name,
+      &handshaker);
+  if (status != GRPC_SECURITY_OK) {
+    cb(exec_ctx, user_data, status, NULL, NULL);
+  } else {
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
+                               nonsecure_endpoint, cb, user_data);
+  }
+}
+
+static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
+                                    grpc_server_security_connector *sc,
+                                    grpc_tcp_server_acceptor *acceptor,
+                                    grpc_endpoint *nonsecure_endpoint,
+                                    grpc_security_handshake_done_cb cb,
+                                    void *user_data) {
+  grpc_ssl_server_security_connector *c =
+      (grpc_ssl_server_security_connector *)sc;
+  tsi_handshaker *handshaker;
+  grpc_security_status status =
+      ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker);
+  if (status != GRPC_SECURITY_OK) {
+    cb(exec_ctx, user_data, status, NULL, NULL);
+  } else {
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
+                               nonsecure_endpoint, cb, user_data);
+  }
+}
+
+static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
+  char *allocated_name = NULL;
+  int r;
+
+  if (strchr(peer_name, ':') != NULL) {
+    char *ignored_port;
+    gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
+    gpr_free(ignored_port);
+    peer_name = allocated_name;
+    if (!peer_name) return 0;
+  }
+  r = tsi_ssl_peer_matches_name(peer, peer_name);
+  gpr_free(allocated_name);
+  return r;
+}
+
+grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
+  size_t i;
+  grpc_auth_context *ctx = NULL;
+  const char *peer_identity_property_name = NULL;
+
+  /* The caller has checked the certificate type property. */
+  GPR_ASSERT(peer->property_count >= 1);
+  ctx = grpc_auth_context_create(NULL);
+  grpc_auth_context_add_cstring_property(
+      ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
+      GRPC_SSL_TRANSPORT_SECURITY_TYPE);
+  for (i = 0; i < peer->property_count; i++) {
+    const tsi_peer_property *prop = &peer->properties[i];
+    if (prop->name == NULL) continue;
+    if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
+      /* If there is no subject alt name, have the CN as the identity. */
+      if (peer_identity_property_name == NULL) {
+        peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME;
+      }
+      grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME,
+                                     prop->value.data, prop->value.length);
+    } else if (strcmp(prop->name,
+                      TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
+      peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME;
+      grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME,
+                                     prop->value.data, prop->value.length);
+    } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) {
+      grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME,
+                                     prop->value.data, prop->value.length);
+    }
+  }
+  if (peer_identity_property_name != NULL) {
+    GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
+                   ctx, peer_identity_property_name) == 1);
+  }
+  return ctx;
+}
+
+static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
+                                           const char *peer_name,
+                                           const tsi_peer *peer,
+                                           grpc_auth_context **auth_context) {
+  /* Check the ALPN. */
+  const tsi_peer_property *p =
+      tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
+  if (p == NULL) {
+    gpr_log(GPR_ERROR, "Missing selected ALPN property.");
+    return GRPC_SECURITY_ERROR;
+  }
+  if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) {
+    gpr_log(GPR_ERROR, "Invalid ALPN value.");
+    return GRPC_SECURITY_ERROR;
+  }
+
+  /* Check the peer name if specified. */
+  if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) {
+    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
+    return GRPC_SECURITY_ERROR;
+  }
+  *auth_context = tsi_ssl_peer_to_auth_context(peer);
+  return GRPC_SECURITY_OK;
+}
+
+static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx,
+                                   grpc_security_connector *sc, tsi_peer peer,
+                                   grpc_security_peer_check_cb cb,
+                                   void *user_data) {
+  grpc_ssl_channel_security_connector *c =
+      (grpc_ssl_channel_security_connector *)sc;
+  grpc_security_status status;
+  grpc_auth_context *auth_context = NULL;
+  status = ssl_check_peer(sc, c->overridden_target_name != NULL
+                                  ? c->overridden_target_name
+                                  : c->target_name,
+                          &peer, &auth_context);
+  cb(exec_ctx, user_data, status, auth_context);
+  grpc_auth_context_unref(auth_context);
+  tsi_peer_destruct(&peer);
+}
+
+static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx,
+                                  grpc_security_connector *sc, tsi_peer peer,
+                                  grpc_security_peer_check_cb cb,
+                                  void *user_data) {
+  grpc_auth_context *auth_context = NULL;
+  grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context);
+  tsi_peer_destruct(&peer);
+  cb(exec_ctx, user_data, status, auth_context);
+  grpc_auth_context_unref(auth_context);
+}
+
+static void add_shallow_auth_property_to_peer(tsi_peer *peer,
+                                              const grpc_auth_property *prop,
+                                              const char *tsi_prop_name) {
+  tsi_peer_property *tsi_prop = &peer->properties[peer->property_count++];
+  tsi_prop->name = (char *)tsi_prop_name;
+  tsi_prop->value.data = prop->value;
+  tsi_prop->value.length = prop->value_length;
+}
+
+tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+    const grpc_auth_context *auth_context) {
+  size_t max_num_props = 0;
+  grpc_auth_property_iterator it;
+  const grpc_auth_property *prop;
+  tsi_peer peer;
+  memset(&peer, 0, sizeof(peer));
+
+  it = grpc_auth_context_property_iterator(auth_context);
+  while (grpc_auth_property_iterator_next(&it) != NULL) max_num_props++;
+
+  if (max_num_props > 0) {
+    peer.properties = gpr_malloc(max_num_props * sizeof(tsi_peer_property));
+    it = grpc_auth_context_property_iterator(auth_context);
+    while ((prop = grpc_auth_property_iterator_next(&it)) != NULL) {
+      if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) {
+        add_shallow_auth_property_to_peer(
+            &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY);
+      } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) {
+        add_shallow_auth_property_to_peer(
+            &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
+      } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) {
+        add_shallow_auth_property_to_peer(&peer, prop,
+                                          TSI_X509_PEM_CERT_PROPERTY);
+      }
+    }
+  }
+  return peer;
+}
+
+void tsi_shallow_peer_destruct(tsi_peer *peer) {
+  if (peer->properties != NULL) gpr_free(peer->properties);
+}
+
+static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+                                        grpc_channel_security_connector *sc,
+                                        const char *host,
+                                        grpc_auth_context *auth_context,
+                                        grpc_security_call_host_check_cb cb,
+                                        void *user_data) {
+  grpc_ssl_channel_security_connector *c =
+      (grpc_ssl_channel_security_connector *)sc;
+  grpc_security_status status = GRPC_SECURITY_ERROR;
+  tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context);
+  if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
+
+  /* If the target name was overridden, then the original target_name was
+     'checked' transitively during the previous peer check at the end of the
+     handshake. */
+  if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
+    status = GRPC_SECURITY_OK;
+  }
+  cb(exec_ctx, user_data, status);
+  tsi_shallow_peer_destruct(&peer);
+}
+
+static grpc_security_connector_vtable ssl_channel_vtable = {
+    ssl_channel_destroy, ssl_channel_check_peer};
+
+static grpc_security_connector_vtable ssl_server_vtable = {
+    ssl_server_destroy, ssl_server_check_peer};
+
+static gpr_slice compute_default_pem_root_certs_once(void) {
+  gpr_slice result = gpr_empty_slice();
+
+  /* First try to load the roots from the environment. */
+  char *default_root_certs_path =
+      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
+  if (default_root_certs_path != NULL) {
+    result = gpr_load_file(default_root_certs_path, 0, NULL);
+    gpr_free(default_root_certs_path);
+  }
+
+  /* Try overridden roots if needed. */
+  grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
+  if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) {
+    char *pem_root_certs = NULL;
+    ovrd_res = ssl_roots_override_cb(&pem_root_certs);
+    if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) {
+      GPR_ASSERT(pem_root_certs != NULL);
+      result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free);
+    }
+  }
+
+  /* Fall back to installed certs if needed. */
+  if (GPR_SLICE_IS_EMPTY(result) &&
+      ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
+    result = gpr_load_file(installed_roots_path, 0, NULL);
+  }
+  return result;
+}
+
+static gpr_slice default_pem_root_certs;
+
+static void init_default_pem_root_certs(void) {
+  default_pem_root_certs = compute_default_pem_root_certs_once();
+}
+
+gpr_slice grpc_get_default_ssl_roots_for_testing(void) {
+  return compute_default_pem_root_certs_once();
+}
+
+static tsi_client_certificate_request_type
+get_tsi_client_certificate_request_type(
+    grpc_ssl_client_certificate_request_type grpc_request_type) {
+  switch (grpc_request_type) {
+    case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE:
+      return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
+
+    case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+      return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
+
+    case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
+      return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY;
+
+    case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+      return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
+
+    case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
+      return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
+
+    default:
+      // Is this a sane default
+      return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
+  }
+}
+
+size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
+  /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
+     loading all the roots once for the lifetime of the process. */
+  static gpr_once once = GPR_ONCE_INIT;
+  gpr_once_init(&once, init_default_pem_root_certs);
+  *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs);
+  return GPR_SLICE_LENGTH(default_pem_root_certs);
+}
+
+grpc_security_status grpc_ssl_channel_security_connector_create(
+    grpc_call_credentials *request_metadata_creds,
+    const grpc_ssl_config *config, const char *target_name,
+    const char *overridden_target_name, grpc_channel_security_connector **sc) {
+  size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
+  const unsigned char **alpn_protocol_strings =
+      gpr_malloc(sizeof(const char *) * num_alpn_protocols);
+  unsigned char *alpn_protocol_string_lengths =
+      gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
+  tsi_result result = TSI_OK;
+  grpc_ssl_channel_security_connector *c;
+  size_t i;
+  const unsigned char *pem_root_certs;
+  size_t pem_root_certs_size;
+  char *port;
+
+  for (i = 0; i < num_alpn_protocols; i++) {
+    alpn_protocol_strings[i] =
+        (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
+    alpn_protocol_string_lengths[i] =
+        (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i));
+  }
+
+  if (config == NULL || target_name == NULL) {
+    gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
+    goto error;
+  }
+  if (config->pem_root_certs == NULL) {
+    pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
+    if (pem_root_certs == NULL || pem_root_certs_size == 0) {
+      gpr_log(GPR_ERROR, "Could not get default pem root certs.");
+      goto error;
+    }
+  } else {
+    pem_root_certs = config->pem_root_certs;
+    pem_root_certs_size = config->pem_root_certs_size;
+  }
+
+  c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector));
+  memset(c, 0, sizeof(grpc_ssl_channel_security_connector));
+
+  gpr_ref_init(&c->base.base.refcount, 1);
+  c->base.base.vtable = &ssl_channel_vtable;
+  c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
+  c->base.request_metadata_creds =
+      grpc_call_credentials_ref(request_metadata_creds);
+  c->base.check_call_host = ssl_channel_check_call_host;
+  c->base.do_handshake = ssl_channel_do_handshake;
+  gpr_split_host_port(target_name, &c->target_name, &port);
+  gpr_free(port);
+  if (overridden_target_name != NULL) {
+    c->overridden_target_name = gpr_strdup(overridden_target_name);
+  }
+  result = tsi_create_ssl_client_handshaker_factory(
+      config->pem_private_key, config->pem_private_key_size,
+      config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
+      pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings,
+      alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols,
+      &c->handshaker_factory);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
+            tsi_result_to_string(result));
+    ssl_channel_destroy(&c->base.base);
+    *sc = NULL;
+    goto error;
+  }
+  *sc = &c->base;
+  gpr_free((void *)alpn_protocol_strings);
+  gpr_free(alpn_protocol_string_lengths);
+  return GRPC_SECURITY_OK;
+
+error:
+  gpr_free((void *)alpn_protocol_strings);
+  gpr_free(alpn_protocol_string_lengths);
+  return GRPC_SECURITY_ERROR;
+}
+
+grpc_security_status grpc_ssl_server_security_connector_create(
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc) {
+  size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
+  const unsigned char **alpn_protocol_strings =
+      gpr_malloc(sizeof(const char *) * num_alpn_protocols);
+  unsigned char *alpn_protocol_string_lengths =
+      gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
+  tsi_result result = TSI_OK;
+  grpc_ssl_server_security_connector *c;
+  size_t i;
+
+  for (i = 0; i < num_alpn_protocols; i++) {
+    alpn_protocol_strings[i] =
+        (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
+    alpn_protocol_string_lengths[i] =
+        (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i));
+  }
+
+  if (config == NULL || config->num_key_cert_pairs == 0) {
+    gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
+    goto error;
+  }
+  c = gpr_malloc(sizeof(grpc_ssl_server_security_connector));
+  memset(c, 0, sizeof(grpc_ssl_server_security_connector));
+
+  gpr_ref_init(&c->base.base.refcount, 1);
+  c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
+  c->base.base.vtable = &ssl_server_vtable;
+  result = tsi_create_ssl_server_handshaker_factory_ex(
+      (const unsigned char **)config->pem_private_keys,
+      config->pem_private_keys_sizes,
+      (const unsigned char **)config->pem_cert_chains,
+      config->pem_cert_chains_sizes, config->num_key_cert_pairs,
+      config->pem_root_certs, config->pem_root_certs_size,
+      get_tsi_client_certificate_request_type(
+          config->client_certificate_request),
+      ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths,
+      (uint16_t)num_alpn_protocols, &c->handshaker_factory);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
+            tsi_result_to_string(result));
+    ssl_server_destroy(&c->base.base);
+    *sc = NULL;
+    goto error;
+  }
+  gpr_mu_init(&c->base.mu);
+  c->base.do_handshake = ssl_server_do_handshake;
+  *sc = &c->base;
+  gpr_free((void *)alpn_protocol_strings);
+  gpr_free(alpn_protocol_string_lengths);
+  return GRPC_SECURITY_OK;
+
+error:
+  gpr_free((void *)alpn_protocol_strings);
+  gpr_free(alpn_protocol_string_lengths);
+  return GRPC_SECURITY_ERROR;
+}
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
new file mode 100644
index 0000000..84e586d
--- /dev/null
+++ b/src/core/lib/security/transport/security_connector.h
@@ -0,0 +1,266 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H
+
+#include <grpc/grpc_security.h>
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/tcp_server.h"
+#include "src/core/lib/tsi/transport_security_interface.h"
+
+/* --- status enum. --- */
+
+typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
+
+/* --- URL schemes. --- */
+
+#define GRPC_SSL_URL_SCHEME "https"
+#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security"
+
+/* --- security_connector object. ---
+
+    A security connector object represents away to configure the underlying
+    transport security mechanism and check the resulting trusted peer.  */
+
+typedef struct grpc_security_connector grpc_security_connector;
+
+#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
+
+typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx,
+                                            void *user_data,
+                                            grpc_security_status status,
+                                            grpc_auth_context *auth_context);
+
+/* Ownership of the secure_endpoint is transfered. */
+typedef void (*grpc_security_handshake_done_cb)(
+    grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status,
+    grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context);
+
+typedef struct {
+  void (*destroy)(grpc_security_connector *sc);
+  void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
+                     tsi_peer peer, grpc_security_peer_check_cb cb,
+                     void *user_data);
+} grpc_security_connector_vtable;
+
+typedef struct grpc_security_connector_handshake_list {
+  void *handshake;
+  struct grpc_security_connector_handshake_list *next;
+} grpc_security_connector_handshake_list;
+
+struct grpc_security_connector {
+  const grpc_security_connector_vtable *vtable;
+  gpr_refcount refcount;
+  const char *url_scheme;
+};
+
+/* Refcounting. */
+#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
+#define GRPC_SECURITY_CONNECTOR_REF(p, r) \
+  grpc_security_connector_ref((p), __FILE__, __LINE__, (r))
+#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \
+  grpc_security_connector_unref((p), __FILE__, __LINE__, (r))
+grpc_security_connector *grpc_security_connector_ref(
+    grpc_security_connector *policy, const char *file, int line,
+    const char *reason);
+void grpc_security_connector_unref(grpc_security_connector *policy,
+                                   const char *file, int line,
+                                   const char *reason);
+#else
+#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p))
+#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p))
+grpc_security_connector *grpc_security_connector_ref(
+    grpc_security_connector *policy);
+void grpc_security_connector_unref(grpc_security_connector *policy);
+#endif
+
+/* Check the peer. Callee takes ownership of the peer object.
+   The callback will include the resulting auth_context. */
+void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
+                                        grpc_security_connector *sc,
+                                        tsi_peer peer,
+                                        grpc_security_peer_check_cb cb,
+                                        void *user_data);
+
+/* Util to encapsulate the connector in a channel arg. */
+grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
+
+/* Util to get the connector from a channel arg. */
+grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg);
+
+/* Util to find the connector from channel args. */
+grpc_security_connector *grpc_find_security_connector_in_args(
+    const grpc_channel_args *args);
+
+/* --- channel_security_connector object. ---
+
+    A channel security connector object represents away to configure the
+    underlying transport security mechanism on the client side.  */
+
+typedef struct grpc_channel_security_connector grpc_channel_security_connector;
+
+typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
+                                                 void *user_data,
+                                                 grpc_security_status status);
+
+struct grpc_channel_security_connector {
+  grpc_security_connector base;
+  grpc_call_credentials *request_metadata_creds;
+  void (*check_call_host)(grpc_exec_ctx *exec_ctx,
+                          grpc_channel_security_connector *sc, const char *host,
+                          grpc_auth_context *auth_context,
+                          grpc_security_call_host_check_cb cb, void *user_data);
+  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
+                       grpc_channel_security_connector *sc,
+                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_security_handshake_done_cb cb, void *user_data);
+};
+
+/* Checks that the host that will be set for a call is acceptable. */
+void grpc_channel_security_connector_check_call_host(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    const char *host, grpc_auth_context *auth_context,
+    grpc_security_call_host_check_cb cb, void *user_data);
+
+/* Handshake. */
+void grpc_channel_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
+    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
+    void *user_data);
+
+/* --- server_security_connector object. ---
+
+    A server security connector object represents away to configure the
+    underlying transport security mechanism on the server side.  */
+
+typedef struct grpc_server_security_connector grpc_server_security_connector;
+
+struct grpc_server_security_connector {
+  grpc_security_connector base;
+  gpr_mu mu;
+  grpc_security_connector_handshake_list *handshaking_handshakes;
+  const grpc_channel_args *channel_args;
+  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
+                       grpc_server_security_connector *sc,
+                       grpc_tcp_server_acceptor *acceptor,
+                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_security_handshake_done_cb cb, void *user_data);
+};
+
+void grpc_server_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+    grpc_security_handshake_done_cb cb, void *user_data);
+
+void grpc_server_security_connector_shutdown(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
+
+/* --- Creation security connectors. --- */
+
+/* For TESTING ONLY!
+   Creates a fake connector that emulates real channel security.  */
+grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
+    grpc_call_credentials *request_metadata_creds);
+
+/* For TESTING ONLY!
+   Creates a fake connector that emulates real server security.  */
+grpc_server_security_connector *grpc_fake_server_security_connector_create(
+    void);
+
+/* Config for ssl clients. */
+typedef struct {
+  unsigned char *pem_private_key;
+  size_t pem_private_key_size;
+  unsigned char *pem_cert_chain;
+  size_t pem_cert_chain_size;
+  unsigned char *pem_root_certs;
+  size_t pem_root_certs_size;
+} grpc_ssl_config;
+
+/* Creates an SSL channel_security_connector.
+   - request_metadata_creds is the credentials object which metadata
+     will be sent with each request. This parameter can be NULL.
+   - config is the SSL config to be used for the SSL channel establishment.
+   - is_client should be 0 for a server or a non-0 value for a client.
+   - secure_peer_name is the secure peer name that should be checked in
+     grpc_channel_security_connector_check_peer. This parameter may be NULL in
+     which case the peer name will not be checked. Note that if this parameter
+     is not NULL, then, pem_root_certs should not be NULL either.
+   - sc is a pointer on the connector to be created.
+  This function returns GRPC_SECURITY_OK in case of success or a
+  specific error code otherwise.
+*/
+grpc_security_status grpc_ssl_channel_security_connector_create(
+    grpc_call_credentials *request_metadata_creds,
+    const grpc_ssl_config *config, const char *target_name,
+    const char *overridden_target_name, grpc_channel_security_connector **sc);
+
+/* Gets the default ssl roots. */
+size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);
+
+/* Exposed for TESTING ONLY!. */
+gpr_slice grpc_get_default_ssl_roots_for_testing(void);
+
+/* Config for ssl servers. */
+typedef struct {
+  unsigned char **pem_private_keys;
+  size_t *pem_private_keys_sizes;
+  unsigned char **pem_cert_chains;
+  size_t *pem_cert_chains_sizes;
+  size_t num_key_cert_pairs;
+  unsigned char *pem_root_certs;
+  size_t pem_root_certs_size;
+  grpc_ssl_client_certificate_request_type client_certificate_request;
+} grpc_ssl_server_config;
+
+/* Creates an SSL server_security_connector.
+   - config is the SSL config to be used for the SSL channel establishment.
+   - sc is a pointer on the connector to be created.
+  This function returns GRPC_SECURITY_OK in case of success or a
+  specific error code otherwise.
+*/
+grpc_security_status grpc_ssl_server_security_connector_create(
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc);
+
+/* Util. */
+const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
+                                                       const char *name);
+
+/* Exposed for testing only. */
+grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer);
+tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+    const grpc_auth_context *auth_context);
+void tsi_shallow_peer_destruct(tsi_peer *peer);
+
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H */
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
new file mode 100644
index 0000000..249f6af
--- /dev/null
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2015, 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 <string.h>
+
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/auth_filters.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+typedef struct call_data {
+  grpc_metadata_batch *recv_initial_metadata;
+  /* Closure to call when finished with the auth_on_recv hook. */
+  grpc_closure *on_done_recv;
+  /* Receive closures are chained: we inject this closure as the on_done_recv
+     up-call on transport_op, and remember to call our on_done_recv member after
+     handling it. */
+  grpc_closure auth_on_recv;
+  grpc_transport_stream_op transport_op;
+  grpc_metadata_array md;
+  const grpc_metadata *consumed_md;
+  size_t num_consumed_md;
+  grpc_auth_context *auth_context;
+} call_data;
+
+typedef struct channel_data {
+  grpc_auth_context *auth_context;
+  grpc_server_credentials *creds;
+} channel_data;
+
+static grpc_metadata_array metadata_batch_to_md_array(
+    const grpc_metadata_batch *batch) {
+  grpc_linked_mdelem *l;
+  grpc_metadata_array result;
+  grpc_metadata_array_init(&result);
+  for (l = batch->list.head; l != NULL; l = l->next) {
+    grpc_metadata *usr_md = NULL;
+    grpc_mdelem *md = l->md;
+    grpc_mdstr *key = md->key;
+    grpc_mdstr *value = md->value;
+    if (result.count == result.capacity) {
+      result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
+      result.metadata =
+          gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata));
+    }
+    usr_md = &result.metadata[result.count++];
+    usr_md->key = grpc_mdstr_as_c_string(key);
+    usr_md->value = grpc_mdstr_as_c_string(value);
+    usr_md->value_length = GPR_SLICE_LENGTH(value->slice);
+  }
+  return result;
+}
+
+static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  size_t i;
+  for (i = 0; i < calld->num_consumed_md; i++) {
+    const grpc_metadata *consumed_md = &calld->consumed_md[i];
+    /* Maybe we could do a pointer comparison but we do not have any guarantee
+       that the metadata processor used the same pointers for consumed_md in the
+       callback. */
+    if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
+        GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
+      continue;
+    }
+    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key,
+               GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
+        memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value,
+               GPR_SLICE_LENGTH(md->value->slice)) == 0) {
+      return NULL; /* Delete. */
+    }
+  }
+  return md;
+}
+
+/* called from application code */
+static void on_md_processing_done(
+    void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
+    const grpc_metadata *response_md, size_t num_response_md,
+    grpc_status_code status, const char *error_details) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  /* TODO(jboeuf): Implement support for response_md. */
+  if (response_md != NULL && num_response_md > 0) {
+    gpr_log(GPR_INFO,
+            "response_md in auth metadata processing not supported for now. "
+            "Ignoring...");
+  }
+
+  if (status == GRPC_STATUS_OK) {
+    calld->consumed_md = consumed_md;
+    calld->num_consumed_md = num_consumed_md;
+    grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md,
+                               elem);
+    grpc_metadata_array_destroy(&calld->md);
+    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1);
+  } else {
+    gpr_slice message;
+    grpc_transport_stream_op close_op;
+    memset(&close_op, 0, sizeof(close_op));
+    grpc_metadata_array_destroy(&calld->md);
+    error_details = error_details != NULL
+                        ? error_details
+                        : "Authentication metadata processing failed.";
+    message = gpr_slice_from_copied_string(error_details);
+    calld->transport_op.send_initial_metadata = NULL;
+    if (calld->transport_op.send_message != NULL) {
+      grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message);
+      calld->transport_op.send_message = NULL;
+    }
+    calld->transport_op.send_trailing_metadata = NULL;
+    grpc_transport_stream_op_add_close(&close_op, status, &message);
+    grpc_call_next_op(&exec_ctx, elem, &close_op);
+    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0);
+  }
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
+                         bool success) {
+  grpc_call_element *elem = user_data;
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  if (success) {
+    if (chand->creds->processor.process != NULL) {
+      calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata);
+      chand->creds->processor.process(
+          chand->creds->processor.state, calld->auth_context,
+          calld->md.metadata, calld->md.count, on_md_processing_done, elem);
+      return;
+    }
+  }
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+}
+
+static void set_recv_ops_md_callbacks(grpc_call_element *elem,
+                                      grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+
+  if (op->recv_initial_metadata != NULL) {
+    /* substitute our callback for the higher callback */
+    calld->recv_initial_metadata = op->recv_initial_metadata;
+    calld->on_done_recv = op->recv_initial_metadata_ready;
+    op->recv_initial_metadata_ready = &calld->auth_on_recv;
+    calld->transport_op = *op;
+  }
+}
+
+/* Called either:
+     - in response to an API call (or similar) from above, to send something
+     - a network event (or similar) from below, to receive something
+   op contains type and call direction information, in addition to the data
+   that is being sent or received. */
+static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                    grpc_call_element *elem,
+                                    grpc_transport_stream_op *op) {
+  set_recv_ops_md_callbacks(elem, op);
+  grpc_call_next_op(exec_ctx, elem, op);
+}
+
+/* Constructor for call_data */
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                           grpc_call_element_args *args) {
+  /* grab pointers to our data from the call element */
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  grpc_server_security_context *server_ctx = NULL;
+
+  /* initialize members */
+  memset(calld, 0, sizeof(*calld));
+  grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
+
+  if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) {
+    args->context[GRPC_CONTEXT_SECURITY].destroy(
+        args->context[GRPC_CONTEXT_SECURITY].value);
+  }
+
+  server_ctx = grpc_server_security_context_create();
+  server_ctx->auth_context = grpc_auth_context_create(chand->auth_context);
+  calld->auth_context = server_ctx->auth_context;
+
+  args->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
+  args->context[GRPC_CONTEXT_SECURITY].destroy =
+      grpc_server_security_context_destroy;
+}
+
+/* Destructor for call_data */
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                              void *ignored) {}
+
+/* Constructor for channel_data */
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {
+  grpc_auth_context *auth_context =
+      grpc_find_auth_context_in_args(args->channel_args);
+  grpc_server_credentials *creds =
+      grpc_find_server_credentials_in_args(args->channel_args);
+  /* grab pointers to our data from the channel element */
+  channel_data *chand = elem->channel_data;
+
+  GPR_ASSERT(!args->is_last);
+  GPR_ASSERT(auth_context != NULL);
+  GPR_ASSERT(creds != NULL);
+
+  /* initialize members */
+  chand->auth_context =
+      GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter");
+  chand->creds = grpc_server_credentials_ref(creds);
+}
+
+/* Destructor for channel data */
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {
+  /* grab pointers to our data from the channel element */
+  channel_data *chand = elem->channel_data;
+  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter");
+  grpc_server_credentials_unref(chand->creds);
+}
+
+const grpc_channel_filter grpc_server_auth_filter = {
+    auth_start_transport_op,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "server-auth"};
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
new file mode 100644
index 0000000..9da42e4
--- /dev/null
+++ b/src/core/lib/security/util/b64.c
@@ -0,0 +1,233 @@
+/*
+ *
+ * Copyright 2015, 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/security/util/b64.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+/* --- Constants. --- */
+
+static const int8_t base64_bytes[] = {
+    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+    -1,   -1,   -1,   -1,   -1,   -1,   -1,   0x3E, -1,   -1,   -1,   0x3F,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1,   -1,
+    -1,   0x7F, -1,   -1,   -1,   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1,   -1,   -1,   -1,   -1,
+    -1,   0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
+    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+    0x31, 0x32, 0x33, -1,   -1,   -1,   -1,   -1};
+
+static const char base64_url_unsafe_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char base64_url_safe_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+#define GRPC_BASE64_PAD_CHAR '='
+#define GRPC_BASE64_PAD_BYTE 0x7F
+#define GRPC_BASE64_MULTILINE_LINE_LEN 76
+#define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4)
+
+/* --- base64 functions. --- */
+
+char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
+                         int multiline) {
+  const unsigned char *data = vdata;
+  const char *base64_chars =
+      url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
+  size_t result_projected_size =
+      4 * ((data_size + 3) / 3) +
+      2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS))
+                     : 0) +
+      1;
+  char *result = gpr_malloc(result_projected_size);
+  char *current = result;
+  size_t num_blocks = 0;
+  size_t i = 0;
+
+  /* Encode each block. */
+  while (data_size >= 3) {
+    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
+    *current++ =
+        base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
+    *current++ =
+        base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)];
+    *current++ = base64_chars[data[i + 2] & 0x3F];
+
+    data_size -= 3;
+    i += 3;
+    if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) {
+      *current++ = '\r';
+      *current++ = '\n';
+      num_blocks = 0;
+    }
+  }
+
+  /* Take care of the tail. */
+  if (data_size == 2) {
+    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
+    *current++ =
+        base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
+    *current++ = base64_chars[(data[i + 1] & 0x0F) << 2];
+    *current++ = GRPC_BASE64_PAD_CHAR;
+  } else if (data_size == 1) {
+    *current++ = base64_chars[(data[i] >> 2) & 0x3F];
+    *current++ = base64_chars[(data[i] & 0x03) << 4];
+    *current++ = GRPC_BASE64_PAD_CHAR;
+    *current++ = GRPC_BASE64_PAD_CHAR;
+  }
+
+  GPR_ASSERT(current >= result);
+  GPR_ASSERT((uintptr_t)(current - result) < result_projected_size);
+  result[current - result] = '\0';
+  return result;
+}
+
+gpr_slice grpc_base64_decode(const char *b64, int url_safe) {
+  return grpc_base64_decode_with_len(b64, strlen(b64), url_safe);
+}
+
+static void decode_one_char(const unsigned char *codes, unsigned char *result,
+                            size_t *result_offset) {
+  uint32_t packed = ((uint32_t)codes[0] << 2) | ((uint32_t)codes[1] >> 4);
+  result[(*result_offset)++] = (unsigned char)packed;
+}
+
+static void decode_two_chars(const unsigned char *codes, unsigned char *result,
+                             size_t *result_offset) {
+  uint32_t packed = ((uint32_t)codes[0] << 10) | ((uint32_t)codes[1] << 4) |
+                    ((uint32_t)codes[2] >> 2);
+  result[(*result_offset)++] = (unsigned char)(packed >> 8);
+  result[(*result_offset)++] = (unsigned char)(packed);
+}
+
+static int decode_group(const unsigned char *codes, size_t num_codes,
+                        unsigned char *result, size_t *result_offset) {
+  GPR_ASSERT(num_codes <= 4);
+
+  /* Short end groups that may not have padding. */
+  if (num_codes == 1) {
+    gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes.");
+    return 0;
+  }
+  if (num_codes == 2) {
+    decode_one_char(codes, result, result_offset);
+    return 1;
+  }
+  if (num_codes == 3) {
+    decode_two_chars(codes, result, result_offset);
+    return 1;
+  }
+
+  /* Regular 4 byte groups with padding or not. */
+  GPR_ASSERT(num_codes == 4);
+  if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) {
+    gpr_log(GPR_ERROR, "Invalid padding detected.");
+    return 0;
+  }
+  if (codes[2] == GRPC_BASE64_PAD_BYTE) {
+    if (codes[3] == GRPC_BASE64_PAD_BYTE) {
+      decode_one_char(codes, result, result_offset);
+    } else {
+      gpr_log(GPR_ERROR, "Invalid padding detected.");
+      return 0;
+    }
+  } else if (codes[3] == GRPC_BASE64_PAD_BYTE) {
+    decode_two_chars(codes, result, result_offset);
+  } else {
+    /* No padding. */
+    uint32_t packed = ((uint32_t)codes[0] << 18) | ((uint32_t)codes[1] << 12) |
+                      ((uint32_t)codes[2] << 6) | codes[3];
+    result[(*result_offset)++] = (unsigned char)(packed >> 16);
+    result[(*result_offset)++] = (unsigned char)(packed >> 8);
+    result[(*result_offset)++] = (unsigned char)(packed);
+  }
+  return 1;
+}
+
+gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
+                                      int url_safe) {
+  gpr_slice result = gpr_slice_malloc(b64_len);
+  unsigned char *current = GPR_SLICE_START_PTR(result);
+  size_t result_size = 0;
+  unsigned char codes[4];
+  size_t num_codes = 0;
+
+  while (b64_len--) {
+    unsigned char c = (unsigned char)(*b64++);
+    signed char code;
+    if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue;
+    if (url_safe) {
+      if (c == '+' || c == '/') {
+        gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c);
+        goto fail;
+      }
+      if (c == '-') {
+        c = '+';
+      } else if (c == '_') {
+        c = '/';
+      }
+    }
+    code = base64_bytes[c];
+    if (code == -1) {
+      if (c != '\r' && c != '\n') {
+        gpr_log(GPR_ERROR, "Invalid character %c", c);
+        goto fail;
+      }
+    } else {
+      codes[num_codes++] = (unsigned char)code;
+      if (num_codes == 4) {
+        if (!decode_group(codes, num_codes, current, &result_size)) goto fail;
+        num_codes = 0;
+      }
+    }
+  }
+
+  if (num_codes != 0 &&
+      !decode_group(codes, num_codes, current, &result_size)) {
+    goto fail;
+  }
+  GPR_SLICE_SET_LENGTH(result, result_size);
+  return result;
+
+fail:
+  gpr_slice_unref(result);
+  return gpr_empty_slice();
+}
diff --git a/src/core/lib/security/util/b64.h b/src/core/lib/security/util/b64.h
new file mode 100644
index 0000000..6908095
--- /dev/null
+++ b/src/core/lib/security/util/b64.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_UTIL_B64_H
+#define GRPC_CORE_LIB_SECURITY_UTIL_B64_H
+
+#include <grpc/support/slice.h>
+
+/* Encodes data using base64. It is the caller's responsability to free
+   the returned char * using gpr_free. Returns NULL on NULL input. */
+char *grpc_base64_encode(const void *data, size_t data_size, int url_safe,
+                         int multiline);
+
+/* Decodes data according to the base64 specification. Returns an empty
+   slice in case of failure. */
+gpr_slice grpc_base64_decode(const char *b64, int url_safe);
+
+/* Same as above except that the length is provided by the caller. */
+gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
+                                      int url_safe);
+
+#endif /* GRPC_CORE_LIB_SECURITY_UTIL_B64_H */
diff --git a/src/core/lib/security/util/json_util.c b/src/core/lib/security/util/json_util.c
new file mode 100644
index 0000000..7eed039
--- /dev/null
+++ b/src/core/lib/security/util/json_util.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015, 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/security/util/json_util.h"
+
+#include <string.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+const char *grpc_json_get_string_property(const grpc_json *json,
+                                          const char *prop_name) {
+  grpc_json *child;
+  for (child = json->child; child != NULL; child = child->next) {
+    if (strcmp(child->key, prop_name) == 0) break;
+  }
+  if (child == NULL || child->type != GRPC_JSON_STRING) {
+    gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name);
+    return NULL;
+  }
+  return child->value;
+}
+
+bool grpc_copy_json_string_property(const grpc_json *json,
+                                    const char *prop_name,
+                                    char **copied_value) {
+  const char *prop_value = grpc_json_get_string_property(json, prop_name);
+  if (prop_value == NULL) return false;
+  *copied_value = gpr_strdup(prop_value);
+  return true;
+}
diff --git a/src/core/lib/security/util/json_util.h b/src/core/lib/security/util/json_util.h
new file mode 100644
index 0000000..1379005
--- /dev/null
+++ b/src/core/lib/security/util/json_util.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2015, 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_SECURITY_UTIL_JSON_UTIL_H
+#define GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H
+
+#include <stdbool.h>
+
+#include "src/core/lib/json/json.h"
+
+// Constants.
+#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
+#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
+#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
+
+// Gets a child property from a json node.
+const char *grpc_json_get_string_property(const grpc_json *json,
+                                          const char *prop_name);
+
+// Copies the value of the json child property specified by prop_name.
+// Returns false if the property was not found.
+bool grpc_copy_json_string_property(const grpc_json *json,
+                                    const char *prop_name, char **copied_value);
+
+#endif /* GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H */
diff --git a/src/core/lib/support/murmur_hash.c b/src/core/lib/support/murmur_hash.c
index 5711fff..7137c1f 100644
--- a/src/core/lib/support/murmur_hash.c
+++ b/src/core/lib/support/murmur_hash.c
@@ -33,6 +33,8 @@
 
 #include "src/core/lib/support/murmur_hash.h"
 
+#include <string.h>
+
 #define ROTL32(x, r) ((x) << (r)) | ((x) >> (32 - (r)))
 
 #define FMIX32(h)    \
@@ -42,10 +44,6 @@
   (h) *= 0xc2b2ae35; \
   (h) ^= (h) >> 16;
 
-/* Block read - if your platform needs to do endian-swapping or can only
-   handle aligned reads, do the conversion here */
-#define GETBLOCK32(p, i) (p)[(i)]
-
 uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed) {
   const uint8_t *data = (const uint8_t *)key;
   const size_t nblocks = len / 4;
@@ -62,7 +60,7 @@
 
   /* body */
   for (i = -(int)nblocks; i; i++) {
-    k1 = GETBLOCK32(blocks, i);
+    memcpy(&k1, blocks + i, sizeof(uint32_t));
 
     k1 *= c1;
     k1 = ROTL32(k1, 15);
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index 1f82c3b..5eb7cf1 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,8 @@
   int shutdown;
   int shutdown_called;
   int is_server_cq;
+  /** Can the server cq accept incoming channels */
+  int is_non_listening_server_cq;
   int num_pluckers;
   plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
   grpc_closure pollset_shutdown_done;
@@ -84,6 +86,7 @@
 };
 
 #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
+#define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1)
 
 static gpr_mu g_freelist_mu;
 static grpc_completion_queue *g_freelist;
@@ -149,6 +152,7 @@
   cc->shutdown = 0;
   cc->shutdown_called = 0;
   cc->is_server_cq = 0;
+  cc->is_non_listening_server_cq = 0;
   cc->num_pluckers = 0;
 #ifndef NDEBUG
   cc->outstanding_tag_count = 0;
@@ -511,6 +515,18 @@
   return POLLSET_FROM_CQ(cc);
 }
 
+grpc_completion_queue *grpc_cq_from_pollset(grpc_pollset *ps) {
+  return CQ_FROM_POLLSET(ps);
+}
+
+void grpc_cq_mark_non_listening_server_cq(grpc_completion_queue *cc) {
+  cc->is_non_listening_server_cq = 1;
+}
+
+bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc) {
+  return (cc->is_non_listening_server_cq == 1);
+}
+
 void grpc_cq_mark_server_cq(grpc_completion_queue *cc) { cc->is_server_cq = 1; }
 
 int grpc_cq_is_server_cq(grpc_completion_queue *cc) { return cc->is_server_cq; }
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index eef82cf..3d0dd13 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,10 @@
                     void *done_arg, grpc_cq_completion *storage);
 
 grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
+grpc_completion_queue *grpc_cq_from_pollset(grpc_pollset *ps);
 
+void grpc_cq_mark_non_listening_server_cq(grpc_completion_queue *cc);
+bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc);
 void grpc_cq_mark_server_cq(grpc_completion_queue *cc);
 int grpc_cq_is_server_cq(grpc_completion_queue *cc);
 
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
index 3fda2c9..7ee7b51 100644
--- a/src/core/lib/surface/init_secure.c
+++ b/src/core/lib/surface/init_secure.c
@@ -37,10 +37,10 @@
 #include <string.h>
 
 #include "src/core/lib/debug/trace.h"
-#include "src/core/lib/security/auth_filters.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/secure_endpoint.h"
-#include "src/core/lib/security/security_connector.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#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/surface/channel_init.h"
 #include "src/core/lib/tsi/transport_security_interface.h"
 
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index aafbc98..14d82b5 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -69,11 +69,6 @@
 typedef struct channel_data channel_data;
 typedef struct registered_method registered_method;
 
-typedef struct {
-  call_data *next;
-  call_data *prev;
-} call_link;
-
 typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
 
 typedef struct requested_call {
@@ -81,7 +76,6 @@
   void *tag;
   grpc_server *server;
   grpc_completion_queue *cq_bound_to_call;
-  grpc_completion_queue *cq_for_notification;
   grpc_call **call;
   grpc_cq_completion completion;
   grpc_metadata_array *initial_metadata;
@@ -108,6 +102,7 @@
   grpc_server *server;
   grpc_connectivity_state connectivity_state;
   grpc_channel *channel;
+  size_t cq_idx;
   /* linked list of all channels on a server */
   channel_data *next;
   channel_data *prev;
@@ -172,7 +167,7 @@
   grpc_server *server;
   call_data *pending_head;
   call_data *pending_tail;
-  gpr_stack_lockfree *requests;
+  gpr_stack_lockfree **requests_per_cq;
 };
 
 struct registered_method {
@@ -180,6 +175,7 @@
   char *host;
   grpc_server_register_method_payload_handling payload_handling;
   uint32_t flags;
+  /* one request matcher per method */
   request_matcher request_matcher;
   registered_method *next;
 };
@@ -195,6 +191,7 @@
   grpc_completion_queue **cqs;
   grpc_pollset **pollsets;
   size_t cq_count;
+  bool started;
 
   /* The two following mutexes control access to server-state
      mu_global controls access to non-call-related state (e.g., channel state)
@@ -207,6 +204,7 @@
   gpr_mu mu_call;   /* mutex for call-specific state */
 
   registered_method *registered_methods;
+  /** one request matcher for unregistered methods */
   request_matcher unregistered_request_matcher;
   /** free list of available requested_calls indices */
   gpr_stack_lockfree *request_freelist;
@@ -234,7 +232,7 @@
 
 static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, bool success);
 static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      requested_call *rc);
+                      size_t cq_idx, requested_call *rc);
 /* Before calling maybe_finish_shutdown, we must hold mu_global and not
    hold mu_call */
 static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_server *server);
@@ -312,12 +310,19 @@
                                  grpc_server *server) {
   memset(rm, 0, sizeof(*rm));
   rm->server = server;
-  rm->requests = gpr_stack_lockfree_create(entries);
+  rm->requests_per_cq =
+      gpr_malloc(sizeof(*rm->requests_per_cq) * server->cq_count);
+  for (size_t i = 0; i < server->cq_count; i++) {
+    rm->requests_per_cq[i] = gpr_stack_lockfree_create(entries);
+  }
 }
 
 static void request_matcher_destroy(request_matcher *rm) {
-  GPR_ASSERT(gpr_stack_lockfree_pop(rm->requests) == -1);
-  gpr_stack_lockfree_destroy(rm->requests);
+  for (size_t i = 0; i < rm->server->cq_count; i++) {
+    GPR_ASSERT(gpr_stack_lockfree_pop(rm->requests_per_cq[i]) == -1);
+    gpr_stack_lockfree_destroy(rm->requests_per_cq[i]);
+  }
+  gpr_free(rm->requests_per_cq);
 }
 
 static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem, bool success) {
@@ -343,8 +348,11 @@
                                           grpc_server *server,
                                           request_matcher *rm) {
   int request_id;
-  while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) {
-    fail_call(exec_ctx, server, &server->requested_calls[request_id]);
+  for (size_t i = 0; i < server->cq_count; i++) {
+    while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) !=
+           -1) {
+      fail_call(exec_ctx, server, i, &server->requested_calls[request_id]);
+    }
   }
 }
 
@@ -364,15 +372,19 @@
   gpr_mu_destroy(&server->mu_call);
   while ((rm = server->registered_methods) != NULL) {
     server->registered_methods = rm->next;
-    request_matcher_destroy(&rm->request_matcher);
+    if (server->started) {
+      request_matcher_destroy(&rm->request_matcher);
+    }
     gpr_free(rm->method);
     gpr_free(rm->host);
     gpr_free(rm);
   }
+  if (server->started) {
+    request_matcher_destroy(&server->unregistered_request_matcher);
+  }
   for (i = 0; i < server->cq_count; i++) {
     GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
   }
-  request_matcher_destroy(&server->unregistered_request_matcher);
   gpr_stack_lockfree_destroy(server->request_freelist);
   gpr_free(server->cqs);
   gpr_free(server->pollsets);
@@ -453,11 +465,11 @@
 }
 
 static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                         call_data *calld, requested_call *rc) {
+                         call_data *calld, size_t cq_idx, requested_call *rc) {
   grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
   grpc_call *call = calld->call;
   *rc->call = call;
-  calld->cq_new = rc->cq_for_notification;
+  calld->cq_new = server->cqs[cq_idx];
   GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
   switch (rc->type) {
     case BATCH_CALL:
@@ -492,7 +504,9 @@
 }
 
 static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  call_data *calld = arg;
+  grpc_call_element *call_elem = arg;
+  call_data *calld = call_elem->call_data;
+  channel_data *chand = call_elem->channel_data;
   request_matcher *rm = calld->request_matcher;
   grpc_server *server = rm->server;
 
@@ -507,26 +521,34 @@
     return;
   }
 
-  int request_id = gpr_stack_lockfree_pop(rm->requests);
-  if (request_id == -1) {
-    gpr_mu_lock(&server->mu_call);
-    gpr_mu_lock(&calld->mu_state);
-    calld->state = PENDING;
-    gpr_mu_unlock(&calld->mu_state);
-    if (rm->pending_head == NULL) {
-      rm->pending_tail = rm->pending_head = calld;
+  for (size_t i = 0; i < server->cq_count; i++) {
+    size_t cq_idx = (chand->cq_idx + i) % server->cq_count;
+    int request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]);
+    if (request_id == -1) {
+      continue;
     } else {
-      rm->pending_tail->pending_next = calld;
-      rm->pending_tail = calld;
+      gpr_mu_lock(&calld->mu_state);
+      calld->state = ACTIVATED;
+      gpr_mu_unlock(&calld->mu_state);
+      publish_call(exec_ctx, server, calld, cq_idx,
+                   &server->requested_calls[request_id]);
+      return; /* early out */
     }
-    calld->pending_next = NULL;
-    gpr_mu_unlock(&server->mu_call);
-  } else {
-    gpr_mu_lock(&calld->mu_state);
-    calld->state = ACTIVATED;
-    gpr_mu_unlock(&calld->mu_state);
-    publish_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
   }
+
+  /* no cq to take the request found: queue it on the slow list */
+  gpr_mu_lock(&server->mu_call);
+  gpr_mu_lock(&calld->mu_state);
+  calld->state = PENDING;
+  gpr_mu_unlock(&calld->mu_state);
+  if (rm->pending_head == NULL) {
+    rm->pending_tail = rm->pending_head = calld;
+  } else {
+    rm->pending_tail->pending_next = calld;
+    rm->pending_tail = calld;
+  }
+  calld->pending_next = NULL;
+  gpr_mu_unlock(&server->mu_call);
 }
 
 static void finish_start_new_rpc(
@@ -548,14 +570,14 @@
 
   switch (payload_handling) {
     case GRPC_SRM_PAYLOAD_NONE:
-      publish_new_rpc(exec_ctx, calld, true);
+      publish_new_rpc(exec_ctx, elem, true);
       break;
     case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
       grpc_op op;
       memset(&op, 0, sizeof(op));
       op.op = GRPC_OP_RECV_MESSAGE;
       op.data.recv_message = &calld->payload;
-      grpc_closure_init(&calld->publish, publish_new_rpc, calld);
+      grpc_closure_init(&calld->publish, publish_new_rpc, elem);
       grpc_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1,
                                         &calld->publish);
       break;
@@ -637,14 +659,16 @@
 
 static void kill_pending_work_locked(grpc_exec_ctx *exec_ctx,
                                      grpc_server *server) {
-  registered_method *rm;
-  request_matcher_kill_requests(exec_ctx, server,
-                                &server->unregistered_request_matcher);
-  request_matcher_zombify_all_pending_calls(
-      exec_ctx, &server->unregistered_request_matcher);
-  for (rm = server->registered_methods; rm; rm = rm->next) {
-    request_matcher_kill_requests(exec_ctx, server, &rm->request_matcher);
-    request_matcher_zombify_all_pending_calls(exec_ctx, &rm->request_matcher);
+  if (server->started) {
+    request_matcher_kill_requests(exec_ctx, server,
+                                  &server->unregistered_request_matcher);
+    request_matcher_zombify_all_pending_calls(
+        exec_ctx, &server->unregistered_request_matcher);
+    for (registered_method *rm = server->registered_methods; rm;
+         rm = rm->next) {
+      request_matcher_kill_requests(exec_ctx, server, &rm->request_matcher);
+      request_matcher_zombify_all_pending_calls(exec_ctx, &rm->request_matcher);
+    }
   }
 }
 
@@ -895,25 +919,46 @@
     "server",
 };
 
-void grpc_server_register_completion_queue(grpc_server *server,
-                                           grpc_completion_queue *cq,
-                                           void *reserved) {
+static void register_completion_queue(grpc_server *server,
+                                      grpc_completion_queue *cq,
+                                      bool is_non_listening, void *reserved) {
   size_t i, n;
-  GRPC_API_TRACE(
-      "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3,
-      (server, cq, reserved));
   GPR_ASSERT(!reserved);
   for (i = 0; i < server->cq_count; i++) {
     if (server->cqs[i] == cq) return;
   }
-  GRPC_CQ_INTERNAL_REF(cq, "server");
+
   grpc_cq_mark_server_cq(cq);
+
+  if (is_non_listening) {
+    grpc_cq_mark_non_listening_server_cq(cq);
+  }
+
+  GRPC_CQ_INTERNAL_REF(cq, "server");
   n = server->cq_count++;
   server->cqs = gpr_realloc(server->cqs,
                             server->cq_count * sizeof(grpc_completion_queue *));
   server->cqs[n] = cq;
 }
 
+void grpc_server_register_completion_queue(grpc_server *server,
+                                           grpc_completion_queue *cq,
+                                           void *reserved) {
+  GRPC_API_TRACE(
+      "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3,
+      (server, cq, reserved));
+  register_completion_queue(server, cq, false, reserved);
+}
+
+void grpc_server_register_non_listening_completion_queue(
+    grpc_server *server, grpc_completion_queue *cq, void *reserved) {
+  GRPC_API_TRACE(
+      "grpc_server_register_non_listening_completion_queue(server=%p, cq=%p, "
+      "reserved=%p)",
+      3, (server, cq, reserved));
+  register_completion_queue(server, cq, true, reserved);
+}
+
 grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
   size_t i;
 
@@ -940,8 +985,6 @@
   for (i = 0; i < (size_t)server->max_requested_calls; i++) {
     gpr_stack_lockfree_push(server->request_freelist, (int)i);
   }
-  request_matcher_init(&server->unregistered_request_matcher,
-                       server->max_requested_calls, server);
   server->requested_calls = gpr_malloc(server->max_requested_calls *
                                        sizeof(*server->requested_calls));
 
@@ -985,8 +1028,6 @@
   }
   m = gpr_malloc(sizeof(registered_method));
   memset(m, 0, sizeof(*m));
-  request_matcher_init(&m->request_matcher, server->max_requested_calls,
-                       server);
   m->method = gpr_strdup(method);
   m->host = gpr_strdup(host);
   m->next = server->registered_methods;
@@ -1003,13 +1044,23 @@
 
   GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
 
+  server->started = true;
+  size_t pollset_count = 0;
   server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
   for (i = 0; i < server->cq_count; i++) {
-    server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
+    if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) {
+      server->pollsets[pollset_count++] = grpc_cq_pollset(server->cqs[i]);
+    }
+  }
+  request_matcher_init(&server->unregistered_request_matcher,
+                       server->max_requested_calls, server);
+  for (registered_method *rm = server->registered_methods; rm; rm = rm->next) {
+    request_matcher_init(&rm->request_matcher, server->max_requested_calls,
+                         server);
   }
 
   for (l = server->listeners; l; l = l->next) {
-    l->start(&exec_ctx, server, l->arg, server->pollsets, server->cq_count);
+    l->start(&exec_ctx, server, l->arg, server->pollsets, pollset_count);
   }
 
   grpc_exec_ctx_finish(&exec_ctx);
@@ -1017,8 +1068,8 @@
 
 void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
                                  grpc_transport *transport,
+                                 grpc_pollset *accepting_pollset,
                                  const grpc_channel_args *args) {
-  size_t i;
   size_t num_registered_methods;
   size_t alloc;
   registered_method *rm;
@@ -1033,12 +1084,6 @@
   uint32_t max_probes = 0;
   grpc_transport_op op;
 
-  for (i = 0; i < s->cq_count; i++) {
-    memset(&op, 0, sizeof(op));
-    op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
-    grpc_transport_perform_op(exec_ctx, transport, &op);
-  }
-
   channel =
       grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport);
   chand = (channel_data *)grpc_channel_stack_element(
@@ -1048,6 +1093,17 @@
   server_ref(s);
   chand->channel = channel;
 
+  size_t cq_idx;
+  grpc_completion_queue *accepting_cq = grpc_cq_from_pollset(accepting_pollset);
+  for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) {
+    if (s->cqs[cq_idx] == accepting_cq) break;
+  }
+  if (cq_idx == s->cq_count) {
+    /* completion queue not found: pick a random one to publish new calls to */
+    cq_idx = (size_t)rand() % s->cq_count;
+  }
+  chand->cq_idx = cq_idx;
+
   num_registered_methods = 0;
   for (rm = s->registered_methods; rm; rm = rm->next) {
     num_registered_methods++;
@@ -1218,19 +1274,19 @@
 }
 
 static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
-                                          grpc_server *server,
+                                          grpc_server *server, size_t cq_idx,
                                           requested_call *rc) {
   call_data *calld = NULL;
   request_matcher *rm = NULL;
   int request_id;
   if (gpr_atm_acq_load(&server->shutdown_flag)) {
-    fail_call(exec_ctx, server, rc);
+    fail_call(exec_ctx, server, cq_idx, rc);
     return GRPC_CALL_OK;
   }
   request_id = gpr_stack_lockfree_pop(server->request_freelist);
   if (request_id == -1) {
     /* out of request ids: just fail this one */
-    fail_call(exec_ctx, server, rc);
+    fail_call(exec_ctx, server, cq_idx, rc);
     return GRPC_CALL_OK;
   }
   switch (rc->type) {
@@ -1243,12 +1299,12 @@
   }
   server->requested_calls[request_id] = *rc;
   gpr_free(rc);
-  if (gpr_stack_lockfree_push(rm->requests, request_id)) {
+  if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) {
     /* this was the first queued request: we need to lock and start
        matching calls */
     gpr_mu_lock(&server->mu_call);
     while ((calld = rm->pending_head) != NULL) {
-      request_id = gpr_stack_lockfree_pop(rm->requests);
+      request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]);
       if (request_id == -1) break;
       rm->pending_head = calld->pending_next;
       gpr_mu_unlock(&server->mu_call);
@@ -1264,7 +1320,7 @@
         GPR_ASSERT(calld->state == PENDING);
         calld->state = ACTIVATED;
         gpr_mu_unlock(&calld->mu_state);
-        publish_call(exec_ctx, server, calld,
+        publish_call(exec_ctx, server, calld, cq_idx,
                      &server->requested_calls[request_id]);
       }
       gpr_mu_lock(&server->mu_call);
@@ -1288,7 +1344,13 @@
       "cq_bound_to_call=%p, cq_for_notification=%p, tag=%p)",
       7, (server, call, details, initial_metadata, cq_bound_to_call,
           cq_for_notification, tag));
-  if (!grpc_cq_is_server_cq(cq_for_notification)) {
+  size_t cq_idx;
+  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
+    if (server->cqs[cq_idx] == cq_for_notification) {
+      break;
+    }
+  }
+  if (cq_idx == server->cq_count) {
     gpr_free(rc);
     error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
     goto done;
@@ -1299,11 +1361,10 @@
   rc->server = server;
   rc->tag = tag;
   rc->cq_bound_to_call = cq_bound_to_call;
-  rc->cq_for_notification = cq_for_notification;
   rc->call = call;
   rc->data.batch.details = details;
   rc->initial_metadata = initial_metadata;
-  error = queue_call_request(&exec_ctx, server, rc);
+  error = queue_call_request(&exec_ctx, server, cq_idx, rc);
 done:
   grpc_exec_ctx_finish(&exec_ctx);
   return error;
@@ -1325,7 +1386,14 @@
       "tag=%p)",
       9, (server, rmp, call, deadline, initial_metadata, optional_payload,
           cq_bound_to_call, cq_for_notification, tag));
-  if (!grpc_cq_is_server_cq(cq_for_notification)) {
+
+  size_t cq_idx;
+  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
+    if (server->cqs[cq_idx] == cq_for_notification) {
+      break;
+    }
+  }
+  if (cq_idx == server->cq_count) {
     gpr_free(rc);
     error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
     goto done;
@@ -1341,26 +1409,25 @@
   rc->server = server;
   rc->tag = tag;
   rc->cq_bound_to_call = cq_bound_to_call;
-  rc->cq_for_notification = cq_for_notification;
   rc->call = call;
   rc->data.registered.registered_method = rm;
   rc->data.registered.deadline = deadline;
   rc->initial_metadata = initial_metadata;
   rc->data.registered.optional_payload = optional_payload;
-  error = queue_call_request(&exec_ctx, server, rc);
+  error = queue_call_request(&exec_ctx, server, cq_idx, rc);
 done:
   grpc_exec_ctx_finish(&exec_ctx);
   return error;
 }
 
 static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      requested_call *rc) {
+                      size_t cq_idx, requested_call *rc) {
   *rc->call = NULL;
   rc->initial_metadata->count = 0;
 
   server_ref(server);
-  grpc_cq_end_op(exec_ctx, rc->cq_for_notification, rc->tag, 0,
-                 done_request_event, rc, &rc->completion);
+  grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, 0, done_request_event,
+                 rc, &rc->completion);
 }
 
 const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h
index 470ef23..fb6e4d6 100644
--- a/src/core/lib/surface/server.h
+++ b/src/core/lib/surface/server.h
@@ -53,6 +53,7 @@
    server */
 void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *server,
                                  grpc_transport *transport,
+                                 grpc_pollset *accepting_pollset,
                                  const grpc_channel_args *args);
 
 const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 5847ec9..82c8e23 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -373,7 +373,8 @@
     ss = g_static_strtab[idx];
     if (ss == NULL) break;
     if (ss->hash == hash && GPR_SLICE_LENGTH(ss->slice) == length &&
-        0 == memcmp(buf, GPR_SLICE_START_PTR(ss->slice), length)) {
+        (length == 0 ||
+         0 == memcmp(buf, GPR_SLICE_START_PTR(ss->slice), length))) {
       GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
       return ss;
     }
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index f955a31..f6c3e57 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -295,7 +295,12 @@
   grpc_channel_args channel_args;
   args->SetChannelArgs(&channel_args);
   server_ = grpc_server_create(&channel_args, nullptr);
-  grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
+  if (thread_pool_ == nullptr) {
+    grpc_server_register_non_listening_completion_queue(server_, cq_.cq(),
+                                                        nullptr);
+  } else {
+    grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
+  }
 }
 
 Server::~Server() {
@@ -407,7 +412,9 @@
       sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr));
     }
     for (size_t i = 0; i < num_cqs; i++) {
-      new UnimplementedAsyncRequest(this, cqs[i]);
+      if (cqs[i]->IsFrequentlyPolled()) {
+        new UnimplementedAsyncRequest(this, cqs[i]);
+      }
     }
   }
   // Start processing rpcs.
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 61f0f6a..54feac3 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -60,8 +60,9 @@
   }
 }
 
-std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
-  ServerCompletionQueue* cq = new ServerCompletionQueue();
+std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue(
+    bool is_frequently_polled) {
+  ServerCompletionQueue* cq = new ServerCompletionQueue(is_frequently_polled);
   cqs_.push_back(cq);
   return std::unique_ptr<ServerCompletionQueue>(cq);
 }
@@ -99,10 +100,12 @@
 
 std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
   std::unique_ptr<ThreadPoolInterface> thread_pool;
+  bool has_sync_methods = false;
   for (auto it = services_.begin(); it != services_.end(); ++it) {
     if ((*it)->service->has_synchronous_methods()) {
       if (thread_pool == nullptr) {
         thread_pool.reset(CreateDefaultThreadPool());
+        has_sync_methods = true;
         break;
       }
     }
@@ -116,6 +119,7 @@
     for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
       if ((*plugin).second->has_sync_methods()) {
         thread_pool.reset(CreateDefaultThreadPool());
+        has_sync_methods = true;
         break;
       }
     }
@@ -128,10 +132,33 @@
   std::unique_ptr<Server> server(
       new Server(thread_pool.release(), true, max_message_size_, &args));
   ServerInitializer* initializer = server->initializer();
+
+  // If the server has atleast one sync methods, we know that this is a Sync
+  // server or a Hybrid server and the completion queue (server->cq_) would be
+  // frequently polled.
+  int num_frequently_polled_cqs = has_sync_methods ? 1 : 0;
+
   for (auto cq = cqs_.begin(); cq != cqs_.end(); ++cq) {
-    grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
-                                          nullptr);
+    // A completion queue that is not polled frequently (by calling Next() or
+    // AsyncNext()) is not safe to use for listening to incoming channels.
+    // Register all such completion queues as non-listening completion queues
+    // with the GRPC core library.
+    if ((*cq)->IsFrequentlyPolled()) {
+      grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
+                                            nullptr);
+      num_frequently_polled_cqs++;
+    } else {
+      grpc_server_register_non_listening_completion_queue(server->server_,
+                                                          (*cq)->cq(), nullptr);
+    }
   }
+
+  if (num_frequently_polled_cqs == 0) {
+    gpr_log(GPR_ERROR,
+            "At least one of the completion queues must be frequently polled");
+    return nullptr;
+  }
+
   for (auto service = services_.begin(); service != services_.end();
        service++) {
     if (!server->RegisterService((*service)->host.get(), (*service)->service)) {
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index d92addb..dcdddc7 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -235,8 +235,16 @@
             await barrier.Task;  // make sure the handler has started.
             cts.Cancel();
 
-            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
-            Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
+            try
+            {
+                // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
+                await call.ResponseAsync;
+                Assert.Fail();
+            }
+            catch (RpcException ex)
+            {
+                Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
+            }
         }
 
         [Test]
@@ -265,9 +273,15 @@
             await handlerStartedBarrier.Task;
             cts.Cancel();
 
-            var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
-            Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
-
+            try
+            {
+                await call.ResponseAsync;
+                Assert.Fail();
+            }
+            catch (RpcException ex)
+            {
+                Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
+            }
             Assert.AreEqual("SUCCESS", await successTcs.Task);
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
index cec8c7c..6a15629 100644
--- a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
@@ -105,7 +105,15 @@
             var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
             await readyToCancelTcs.Task;
             cts.Cancel();
-            Assert.ThrowsAsync(typeof(RpcException), async () => await parentCall);
+            try
+            {
+                // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
+                await parentCall;
+                Assert.Fail();
+            }
+            catch (RpcException)
+            {
+            }
             Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task);
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
index ab12c12..6fe3827 100644
--- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
+++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
@@ -32,7 +32,7 @@
 #endregion
 
 using System;
-using System.Threading;
+using System.Linq;
 using Grpc.Core;
 using NUnit.Framework;
 
@@ -44,7 +44,11 @@
         public void InitializeAndShutdownGrpcEnvironment()
         {
             var env = GrpcEnvironment.AddRef();
-            Assert.IsNotNull(env.CompletionQueue);
+            Assert.IsTrue(env.CompletionQueues.Count > 0);
+            for (int i = 0; i < env.CompletionQueues.Count; i++)
+            {
+                Assert.IsNotNull(env.CompletionQueues.ElementAt(i));
+            }
             GrpcEnvironment.Release();
         }
 
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
index 0e20476..c35aaf6 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
@@ -53,8 +53,6 @@
         [SetUp]
         public void Init()
         {
-            var environment = GrpcEnvironment.AddRef();
-
             // Create a fake server just so we have an instance to refer to.
             // The server won't actually be used at all.
             server = new Server()
@@ -66,7 +64,6 @@
             fakeCall = new FakeNativeCall();
             asyncCallServer = new AsyncCallServer<string, string>(
                 Marshallers.StringMarshaller.Serializer, Marshallers.StringMarshaller.Deserializer,
-                environment,
                 server);
             asyncCallServer.InitializeForTesting(fakeCall);
         }
@@ -75,7 +72,6 @@
         public void Cleanup()
         {
             server.ShutdownAsync().Wait();
-            GrpcEnvironment.Release();
         }
 
         [Test]
@@ -136,7 +132,6 @@
         public void WriteAfterCancelNotificationFails()
         {
             var finishedTask = asyncCallServer.ServerSideCallAsync();
-            var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
             var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
 
             fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
@@ -181,6 +176,21 @@
             AssertFinished(asyncCallServer, fakeCall, finishedTask);
         }
 
+        [Test]
+        public void WriteAfterWriteStatusThrowsInvalidOperationException()
+        {
+            var finishedTask = asyncCallServer.ServerSideCallAsync();
+            var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
+
+            asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null);
+            Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await responseStream.WriteAsync("request1"));
+
+            fakeCall.SendStatusFromServerHandler(true);
+            fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
+
+            AssertFinished(asyncCallServer, fakeCall, finishedTask);
+        }
+
         static void AssertFinished(AsyncCallServer<string, string> asyncCallServer, FakeNativeCall fakeCall, Task finishedTask)
         {
             Assert.IsTrue(fakeCall.IsDisposed);
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
index 777a1c8..81897f8 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
@@ -33,7 +33,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
 using Grpc.Core.Internal;
@@ -82,7 +81,7 @@
             Assert.ThrowsAsync(typeof(InvalidOperationException),
                 async () => await asyncCall.ReadMessageAsync());
             Assert.Throws(typeof(InvalidOperationException),
-                () => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {}));
+                () => asyncCall.SendMessageAsync("abc", new WriteFlags()));
         }
 
         [Test]
@@ -103,7 +102,7 @@
             var resultTask = asyncCall.UnaryCallAsync("request1");
             fakeCall.UnaryResponseClientHandler(true,
                 CreateClientSideStatus(StatusCode.InvalidArgument),
-                CreateResponsePayload(),
+                null,
                 new Metadata());
 
             AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
@@ -148,7 +147,7 @@
             var resultTask = asyncCall.ClientStreamingCallAsync();
             fakeCall.UnaryResponseClientHandler(true,
                 CreateClientSideStatus(StatusCode.InvalidArgument),
-                CreateResponsePayload(),
+                null,
                 new Metadata());
 
             AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
@@ -193,7 +192,7 @@
 
             fakeCall.UnaryResponseClientHandler(true,
                 CreateClientSideStatus(StatusCode.Internal),
-                CreateResponsePayload(),
+                null,
                 new Metadata());
 
             AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
@@ -211,7 +210,9 @@
                 new Metadata());
 
             AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
-            var ex = Assert.Throws<RpcException>(() => requestStream.WriteAsync("request1"));
+
+            var writeTask = requestStream.WriteAsync("request1");
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
             Assert.AreEqual(Status.DefaultSuccess, ex.Status);
         }
 
@@ -223,11 +224,13 @@
 
             fakeCall.UnaryResponseClientHandler(true,
                 new ClientSideStatus(new Status(StatusCode.OutOfRange, ""), new Metadata()),
-                CreateResponsePayload(),
+                null,
                 new Metadata());
 
             AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.OutOfRange);
-            var ex = Assert.Throws<RpcException>(() => requestStream.WriteAsync("request1"));
+
+            var writeTask = requestStream.WriteAsync("request1");
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
             Assert.AreEqual(StatusCode.OutOfRange, ex.Status.StatusCode);
         }
 
@@ -267,7 +270,7 @@
         }
 
         [Test]
-        public void ClientStreaming_WriteAfterCancellationRequestThrowsOperationCancelledException()
+        public void ClientStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException()
         {
             var resultTask = asyncCall.ClientStreamingCallAsync();
             var requestStream = new ClientRequestStream<string, string>(asyncCall);
@@ -275,11 +278,12 @@
             asyncCall.Cancel();
             Assert.IsTrue(fakeCall.IsCancelled);
 
-            Assert.Throws(typeof(OperationCanceledException), () => requestStream.WriteAsync("request1"));
+            var writeTask = requestStream.WriteAsync("request1");
+            Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask);
 
             fakeCall.UnaryResponseClientHandler(true,
                 CreateClientSideStatus(StatusCode.Cancelled),
-                CreateResponsePayload(),
+                null,
                 new Metadata());
 
             AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Cancelled);
@@ -290,7 +294,7 @@
         {
             asyncCall.StartServerStreamingCall("request1");
             Assert.Throws(typeof(InvalidOperationException),
-                () => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {}));
+                () => asyncCall.SendMessageAsync("abc", new WriteFlags()));
         }
 
         [Test]
@@ -390,12 +394,13 @@
 
             AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask);
 
-            var ex = Assert.ThrowsAsync<RpcException>(async () => await requestStream.WriteAsync("request1"));
+            var writeTask = requestStream.WriteAsync("request1");
+            var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
             Assert.AreEqual(Status.DefaultSuccess, ex.Status);
         }
 
         [Test]
-        public void DuplexStreaming_CompleteAfterReceivingStatusFails()
+        public void DuplexStreaming_CompleteAfterReceivingStatusSuceeds()
         {
             asyncCall.StartDuplexStreamingCall();
             var requestStream = new ClientRequestStream<string, string>(asyncCall);
@@ -411,7 +416,7 @@
         }
 
         [Test]
-        public void DuplexStreaming_WriteAfterCancellationRequestThrowsOperationCancelledException()
+        public void DuplexStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException()
         {
             asyncCall.StartDuplexStreamingCall();
             var requestStream = new ClientRequestStream<string, string>(asyncCall);
@@ -419,7 +424,9 @@
 
             asyncCall.Cancel();
             Assert.IsTrue(fakeCall.IsCancelled);
-            Assert.Throws(typeof(OperationCanceledException), () => requestStream.WriteAsync("request1"));
+
+            var writeTask = requestStream.WriteAsync("request1");
+            Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask);
 
             var readTask = responseStream.MoveNext();
             fakeCall.ReceivedMessageHandler(true, null);
diff --git a/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs
index c6843f1..195119f 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs
@@ -60,7 +60,7 @@
             var ev = cq.Next();
             cq.Dispose();
             GrpcEnvironment.Release();
-            Assert.AreEqual(GRPCCompletionType.Shutdown, ev.type);
+            Assert.AreEqual(CompletionQueueEvent.CompletionType.Shutdown, ev.type);
             Assert.AreNotEqual(IntPtr.Zero, ev.success);
             Assert.AreEqual(IntPtr.Zero, ev.tag);
         }
diff --git a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
index 74f7f24..c124ea2 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
@@ -61,15 +61,15 @@
         }
 
         [Test]
-        public void InfFuture()
+        public void InfFutureMatchesNativeValue()
         {
-            var timespec = Timespec.InfFuture;
+            Assert.AreEqual(Timespec.NativeInfFuture, Timespec.InfFuture);
         }
 
         [Test]
-        public void InfPast()
+        public void InfPastMatchesNativeValue()
         {
-            var timespec = Timespec.InfPast;
+            Assert.AreEqual(Timespec.NativeInfPast, Timespec.InfPast);
         }
 
         [Test]
@@ -108,7 +108,7 @@
             Assert.Throws(typeof(InvalidOperationException),
                 () => new Timespec(0, 1000 * 1000 * 1000).ToDateTime());
             Assert.Throws(typeof(InvalidOperationException),
-                () => new Timespec(0, 0, GPRClockType.Monotonic).ToDateTime());
+                () => new Timespec(0, 0, ClockType.Monotonic).ToDateTime());
         }
 
         [Test]
diff --git a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
index 0663e77..d770f82 100644
--- a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs
@@ -134,7 +134,15 @@
         {
             helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
             {
-                Assert.ThrowsAsync<IOException>(async () => await requestStream.MoveNext());
+                try
+                {
+                    // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
+                    await requestStream.MoveNext();
+                    Assert.Fail();
+                }
+                catch (IOException)
+                {
+                }
                 return "RESPONSE";
             });
 
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 93a6e6a..886adfe 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -31,7 +31,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -56,6 +55,7 @@
 
         readonly string target;
         readonly GrpcEnvironment environment;
+        readonly CompletionQueueSafeHandle completionQueue;
         readonly ChannelSafeHandle handle;
         readonly Dictionary<string, ChannelOption> options;
 
@@ -75,6 +75,7 @@
             EnsureUserAgentChannelOption(this.options);
             this.environment = GrpcEnvironment.AddRef();
 
+            this.completionQueue = this.environment.PickCompletionQueue();
             using (var nativeCredentials = credentials.ToNativeCredentials())
             using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options.Values))
             {
@@ -135,7 +136,7 @@
                     tcs.SetCanceled();
                 }
             });
-            handle.WatchConnectivityState(lastObservedState, deadlineTimespec, environment.CompletionQueue, environment.CompletionRegistry, handler);
+            handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, handler);
             return tcs.Task;
         }
 
@@ -231,6 +232,14 @@
             }
         }
 
+        internal CompletionQueueSafeHandle CompletionQueue
+        {
+            get
+            {
+                return this.completionQueue;
+            }
+        }
+
         internal void AddCallReference(object call)
         {
             activeCallCounter.Increment();
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 95077a6..a8b7b5f 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -74,7 +74,6 @@
     <Compile Include="Internal\CallSafeHandle.cs" />
     <Compile Include="Internal\ChannelSafeHandle.cs" />
     <Compile Include="Internal\CompletionQueueSafeHandle.cs" />
-    <Compile Include="Internal\Enums.cs" />
     <Compile Include="Internal\SafeHandleZeroIsInvalid.cs" />
     <Compile Include="Internal\Timespec.cs" />
     <Compile Include="Internal\GrpcThreadPool.cs" />
@@ -87,7 +86,6 @@
     <Compile Include="Utils\BenchmarkUtil.cs" />
     <Compile Include="ChannelCredentials.cs" />
     <Compile Include="Internal\ChannelArgsSafeHandle.cs" />
-    <Compile Include="Internal\AsyncCompletion.cs" />
     <Compile Include="Internal\AsyncCallBase.cs" />
     <Compile Include="Internal\AsyncCallServer.cs" />
     <Compile Include="Internal\AsyncCall.cs" />
@@ -134,6 +132,10 @@
     <Compile Include="DefaultCallInvoker.cs" />
     <Compile Include="Internal\UnimplementedCallInvoker.cs" />
     <Compile Include="Internal\InterceptingCallInvoker.cs" />
+    <Compile Include="Internal\ServerRpcNew.cs" />
+    <Compile Include="Internal\ClientSideStatus.cs" />
+    <Compile Include="Internal\ClockType.cs" />
+    <Compile Include="Internal\CallError.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Grpc.Core.nuspec" />
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index bee0ef1..18af109 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -32,8 +32,9 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using System.Runtime.InteropServices;
-using System.Threading.Tasks;
 using Grpc.Core.Internal;
 using Grpc.Core.Logging;
 using Grpc.Core.Utils;
@@ -51,12 +52,13 @@
         static GrpcEnvironment instance;
         static int refCount;
         static int? customThreadPoolSize;
+        static int? customCompletionQueueCount;
 
         static ILogger logger = new ConsoleLogger();
 
         readonly GrpcThreadPool threadPool;
-        readonly CompletionRegistry completionRegistry;
         readonly DebugStats debugStats = new DebugStats();
+        readonly AtomicCounter cqPickerCounter = new AtomicCounter();
         bool isClosed;
 
         /// <summary>
@@ -141,36 +143,51 @@
         }
 
         /// <summary>
+        /// Sets the number of completion queues in the  gRPC thread pool that polls for internal RPC events.
+        /// Can be only invoke before the <c>GrpcEnviroment</c> is started and cannot be changed afterwards.
+        /// Setting the number of completions queues is an advanced setting and you should only use it if you know what you are doing.
+        /// Most users should rely on the default value provided by gRPC library.
+        /// Note: this method is part of an experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static void SetCompletionQueueCount(int completionQueueCount)
+        {
+            lock (staticLock)
+            {
+                GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized");
+                GrpcPreconditions.CheckArgument(completionQueueCount > 0, "threadCount needs to be a positive number");
+                customCompletionQueueCount = completionQueueCount;
+            }
+        }
+
+        /// <summary>
         /// Creates gRPC environment.
         /// </summary>
         private GrpcEnvironment()
         {
             GrpcNativeInit();
-            completionRegistry = new CompletionRegistry(this);
-            threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault());
+            threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault());
             threadPool.Start();
         }
 
         /// <summary>
-        /// Gets the completion registry used by this gRPC environment.
+        /// Gets the completion queues used by this gRPC environment.
         /// </summary>
-        internal CompletionRegistry CompletionRegistry
+        internal IReadOnlyCollection<CompletionQueueSafeHandle> CompletionQueues
         {
             get
             {
-                return this.completionRegistry;
+                return this.threadPool.CompletionQueues;
             }
         }
 
         /// <summary>
-        /// Gets the completion queue used by this gRPC environment.
+        /// Picks a completion queue in a round-robin fashion.
+        /// Shouldn't be invoked on a per-call basis (used at per-channel basis).
         /// </summary>
-        internal CompletionQueueSafeHandle CompletionQueue
+        internal CompletionQueueSafeHandle PickCompletionQueue()
         {
-            get
-            {
-                return this.threadPool.CompletionQueue;
-            }
+            var cqIndex = (int) ((cqPickerCounter.Increment() - 1) % this.threadPool.CompletionQueues.Count);
+            return this.threadPool.CompletionQueues.ElementAt(cqIndex);
         }
 
         /// <summary>
@@ -230,5 +247,15 @@
             // more work, but seems to work reasonably well for a start.
             return Math.Max(MinDefaultThreadPoolSize, Environment.ProcessorCount / 2);
         }
+
+        private int GetCompletionQueueCountOrDefault()
+        {
+            if (customCompletionQueueCount.HasValue)
+            {
+                return customCompletionQueueCount.Value;
+            }
+            // by default, create a completion queue for each thread
+            return GetThreadPoolSizeOrDefault();
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 5535186..895be69 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -32,12 +32,7 @@
 #endregion
 
 using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
 using System.Threading.Tasks;
-using Grpc.Core.Internal;
 using Grpc.Core.Logging;
 using Grpc.Core.Profiling;
 using Grpc.Core.Utils;
@@ -57,9 +52,11 @@
         // Completion of a pending unary response if not null.
         TaskCompletionSource<TResponse> unaryResponseTcs;
 
+        // TODO(jtattermusch): this field doesn't need to be initialized for unary response calls.
         // Indicates that response streaming call has finished.
         TaskCompletionSource<object> streamingCallFinishedTcs = new TaskCompletionSource<object>();
 
+        // TODO(jtattermusch): this field could be lazy-initialized (only if someone requests the response headers).
         // Response headers set here once received.
         TaskCompletionSource<Metadata> responseHeadersTcs = new TaskCompletionSource<Metadata>();
 
@@ -67,7 +64,7 @@
         ClientSideStatus? finishedStatus;
 
         public AsyncCall(CallInvocationDetails<TRequest, TResponse> callDetails)
-            : base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer, callDetails.Channel.Environment)
+            : base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer)
         {
             this.details = callDetails.WithOptions(callDetails.Options.Normalize());
             this.initialMetadataSent = true;  // we always send metadata at the very beginning of the call.
@@ -144,7 +141,7 @@
                 GrpcPreconditions.CheckState(!started);
                 started = true;
 
-                Initialize(environment.CompletionQueue);
+                Initialize(details.Channel.CompletionQueue);
 
                 halfcloseRequested = true;
                 readingDone = true;
@@ -171,7 +168,7 @@
                 GrpcPreconditions.CheckState(!started);
                 started = true;
 
-                Initialize(environment.CompletionQueue);
+                Initialize(details.Channel.CompletionQueue);
 
                 readingDone = true;
 
@@ -195,7 +192,7 @@
                 GrpcPreconditions.CheckState(!started);
                 started = true;
 
-                Initialize(environment.CompletionQueue);
+                Initialize(details.Channel.CompletionQueue);
 
                 halfcloseRequested = true;
 
@@ -220,7 +217,7 @@
                 GrpcPreconditions.CheckState(!started);
                 started = true;
 
-                Initialize(environment.CompletionQueue);
+                Initialize(details.Channel.CompletionQueue);
 
                 using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                 {
@@ -232,11 +229,10 @@
 
         /// <summary>
         /// Sends a streaming request. Only one pending send action is allowed at any given time.
-        /// completionDelegate is called when the operation finishes.
         /// </summary>
-        public void StartSendMessage(TRequest msg, WriteFlags writeFlags, AsyncCompletionDelegate<object> completionDelegate)
+        public Task SendMessageAsync(TRequest msg, WriteFlags writeFlags)
         {
-            StartSendMessageInternal(msg, writeFlags, completionDelegate);
+            return SendMessageInternalAsync(msg, writeFlags);
         }
 
         /// <summary>
@@ -250,29 +246,32 @@
         /// <summary>
         /// Sends halfclose, indicating client is done with streaming requests.
         /// Only one pending send action is allowed at any given time.
-        /// completionDelegate is called when the operation finishes.
         /// </summary>
-        public void StartSendCloseFromClient(AsyncCompletionDelegate<object> completionDelegate)
+        public Task SendCloseFromClientAsync()
         {
             lock (myLock)
             {
-                GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
-                CheckSendingAllowed(allowFinished: true);
+                GrpcPreconditions.CheckState(started);
 
-                if (!disposed && !finished)
+                var earlyResult = CheckSendPreconditionsClientSide();
+                if (earlyResult != null)
                 {
-                    call.StartSendCloseFromClient(HandleSendCloseFromClientFinished);
+                    return earlyResult;
                 }
-                else
+
+                if (disposed || finished)
                 {
                     // In case the call has already been finished by the serverside,
-                    // the halfclose has already been done implicitly, so we only
-                    // emit the notification for the completion delegate.
-                    Task.Run(() => HandleSendCloseFromClientFinished(true));
+                    // the halfclose has already been done implicitly, so just return
+                    // completed task here.
+                    halfcloseRequested = true;
+                    return Task.FromResult<object>(null);
                 }
+                call.StartSendCloseFromClient(HandleSendCloseFromClientFinished);
 
                 halfcloseRequested = true;
-                sendCompletionDelegate = completionDelegate;
+                streamingWriteTcs = new TaskCompletionSource<object>();
+                return streamingWriteTcs.Task;
             }
         }
 
@@ -342,6 +341,45 @@
             get { return true; }
         }
 
+        protected override Task CheckSendAllowedOrEarlyResult()
+        {
+            var earlyResult = CheckSendPreconditionsClientSide();
+            if (earlyResult != null)
+            {
+                return earlyResult;
+            }
+
+            if (finishedStatus.HasValue)
+            {
+                // throwing RpcException if we already received status on client
+                // side makes the most sense.
+                // Note that this throws even for StatusCode.OK.
+                // Writing after the call has finished is not a programming error because server can close
+                // the call anytime, so don't throw directly, but let the write task finish with an error.
+                var tcs = new TaskCompletionSource<object>();
+                tcs.SetException(new RpcException(finishedStatus.Value.Status));
+                return tcs.Task;
+            }
+
+            return null;
+        }
+
+        private Task CheckSendPreconditionsClientSide()
+        {
+            GrpcPreconditions.CheckState(!halfcloseRequested, "Request stream has already been completed.");
+            GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time.");
+
+            if (cancelRequested)
+            {
+                // Return a cancelled task.
+                var tcs = new TaskCompletionSource<object>();
+                tcs.SetCanceled();
+                return tcs.Task;
+            }
+
+            return null;
+        }
+
         private void Initialize(CompletionQueueSafeHandle cq)
         {
             using (Profilers.ForCurrentThread().NewScope("AsyncCall.Initialize"))
@@ -368,7 +406,7 @@
                 var credentials = details.Options.Credentials;
                 using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null)
                 {
-                    var result = details.Channel.Handle.CreateCall(environment.CompletionRegistry,
+                    var result = details.Channel.Handle.CreateCall(
                                  parentCall, ContextPropagationToken.DefaultMask, cq,
                                  details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials);
                     return result;
@@ -400,6 +438,7 @@
         /// </summary>
         private void HandleReceivedResponseHeaders(bool success, Metadata responseHeaders)
         {
+            // TODO(jtattermusch): handle success==false
             responseHeadersTcs.SetResult(responseHeaders);
         }
 
@@ -443,19 +482,6 @@
             }
         }
 
-        protected override void CheckSendingAllowed(bool allowFinished)
-        {
-            base.CheckSendingAllowed(true);
-
-            // throwing RpcException if we already received status on client
-            // side makes the most sense.
-            // Note that this throws even for StatusCode.OK.
-            if (!allowFinished && finishedStatus.HasValue)
-            {
-                throw new RpcException(finishedStatus.Value.Status);
-            }
-        }
-
         /// <summary>
         /// Handles receive status completion for calls with streaming response.
         /// </summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 4de2370..cb8366c 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -58,7 +58,6 @@
         readonly Func<TWrite, byte[]> serializer;
         readonly Func<byte[], TRead> deserializer;
 
-        protected readonly GrpcEnvironment environment;
         protected readonly object myLock = new object();
 
         protected INativeCall call;
@@ -67,8 +66,8 @@
         protected bool started;
         protected bool cancelRequested;
 
-        protected AsyncCompletionDelegate<object> sendCompletionDelegate;  // Completion of a pending send or sendclose if not null.
         protected TaskCompletionSource<TRead> streamingReadTcs;  // Completion of a pending streaming read if not null.
+        protected TaskCompletionSource<object> streamingWriteTcs;  // Completion of a pending streaming write or send close from client if not null.
         protected TaskCompletionSource<object> sendStatusFromServerTcs;
 
         protected bool readingDone;  // True if last read (i.e. read with null payload) was already received.
@@ -78,11 +77,10 @@
         protected bool initialMetadataSent;
         protected long streamingWritesCounter;  // Number of streaming send operations started so far.
 
-        public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer, GrpcEnvironment environment)
+        public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer)
         {
             this.serializer = GrpcPreconditions.CheckNotNull(serializer);
             this.deserializer = GrpcPreconditions.CheckNotNull(deserializer);
-            this.environment = GrpcPreconditions.CheckNotNull(environment);
         }
 
         /// <summary>
@@ -128,28 +126,31 @@
 
         /// <summary>
         /// Initiates sending a message. Only one send operation can be active at a time.
-        /// completionDelegate is invoked upon completion.
         /// </summary>
-        protected void StartSendMessageInternal(TWrite msg, WriteFlags writeFlags, AsyncCompletionDelegate<object> completionDelegate)
+        protected Task SendMessageInternalAsync(TWrite msg, WriteFlags writeFlags)
         {
             byte[] payload = UnsafeSerialize(msg);
 
             lock (myLock)
             {
-                GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
-                CheckSendingAllowed(allowFinished: false);
+                GrpcPreconditions.CheckState(started);
+                var earlyResult = CheckSendAllowedOrEarlyResult();
+                if (earlyResult != null)
+                {
+                    return earlyResult;
+                }
 
                 call.StartSendMessage(HandleSendFinished, payload, writeFlags, !initialMetadataSent);
 
-                sendCompletionDelegate = completionDelegate;
                 initialMetadataSent = true;
                 streamingWritesCounter++;
+                streamingWriteTcs = new TaskCompletionSource<object>();
+                return streamingWriteTcs.Task;
             }
         }
 
         /// <summary>
         /// Initiates reading a message. Only one read operation can be active at a time.
-        /// completionDelegate is invoked upon completion.
         /// </summary>
         protected Task<TRead> ReadMessageInternalAsync()
         {
@@ -159,7 +160,7 @@
                 if (readingDone)
                 {
                     // the last read that returns null or throws an exception is idempotent
-                    // and maintain its state.
+                    // and maintains its state.
                     GrpcPreconditions.CheckState(streamingReadTcs != null, "Call does not support streaming reads.");
                     return streamingReadTcs.Task;
                 }
@@ -183,7 +184,7 @@
             {
                 if (!disposed && call != null)
                 {
-                    bool noMoreSendCompletions = sendCompletionDelegate == null && (halfcloseRequested || cancelRequested || finished);
+                    bool noMoreSendCompletions = streamingWriteTcs == null && (halfcloseRequested || cancelRequested || finished);
                     if (noMoreSendCompletions && readingDone && finished)
                     {
                         ReleaseResources();
@@ -213,24 +214,11 @@
         {
         }
 
-        protected virtual void CheckSendingAllowed(bool allowFinished)
-        {
-            GrpcPreconditions.CheckState(started);
-            CheckNotCancelled();
-            GrpcPreconditions.CheckState(!disposed || allowFinished);
-
-            GrpcPreconditions.CheckState(!halfcloseRequested, "Already halfclosed.");
-            GrpcPreconditions.CheckState(!finished || allowFinished, "Already finished.");
-            GrpcPreconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time");
-        }
-
-        protected void CheckNotCancelled()
-        {
-            if (cancelRequested)
-            {
-                throw new OperationCanceledException("Remote call has been cancelled.");
-            }
-        }
+        /// <summary>
+        /// Checks if sending is allowed and possibly returns a Task that allows short-circuiting the send
+        /// logic by directly returning the write operation result task. Normally, null is returned.
+        /// </summary>
+        protected abstract Task CheckSendAllowedOrEarlyResult();
 
         protected byte[] UnsafeSerialize(TWrite msg)
         {
@@ -259,39 +247,27 @@
             }
         }
 
-        protected void FireCompletion<T>(AsyncCompletionDelegate<T> completionDelegate, T value, Exception error)
-        {
-            try
-            {
-                completionDelegate(value, error);
-            }
-            catch (Exception e)
-            {
-                Logger.Error(e, "Exception occured while invoking completion delegate.");
-            }
-        }
-
         /// <summary>
         /// Handles send completion.
         /// </summary>
         protected void HandleSendFinished(bool success)
         {
-            AsyncCompletionDelegate<object> origCompletionDelegate = null;
+            TaskCompletionSource<object> origTcs = null;
             lock (myLock)
             {
-                origCompletionDelegate = sendCompletionDelegate;
-                sendCompletionDelegate = null;
+                origTcs = streamingWriteTcs;
+                streamingWriteTcs = null;
 
                 ReleaseResourcesIfPossible();
             }
 
             if (!success)
             {
-                FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Send failed"));
+                origTcs.SetException(new InvalidOperationException("Send failed"));
             }
             else
             {
-                FireCompletion(origCompletionDelegate, null, null);
+                origTcs.SetResult(null);
             }
         }
 
@@ -300,22 +276,23 @@
         /// </summary>
         protected void HandleSendCloseFromClientFinished(bool success)
         {
-            AsyncCompletionDelegate<object> origCompletionDelegate = null;
+            TaskCompletionSource<object> origTcs = null;
             lock (myLock)
             {
-                origCompletionDelegate = sendCompletionDelegate;
-                sendCompletionDelegate = null;
+                origTcs = streamingWriteTcs;
+                streamingWriteTcs = null;
 
                 ReleaseResourcesIfPossible();
             }
 
             if (!success)
             {
-                FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Sending close from client has failed."));
+                // TODO(jtattermusch): this method is same as HandleSendFinished (only the error message differs).
+                origTcs.SetException(new InvalidOperationException("Sending close from client has failed."));
             }
             else
             {
-                FireCompletion(origCompletionDelegate, null, null);
+                origTcs.SetResult(null);
             }
         }
 
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index b1566b4..56c23ba 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -51,14 +51,14 @@
         readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
         readonly Server server;
 
-        public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer, GrpcEnvironment environment, Server server) : base(serializer, deserializer, environment)
+        public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer, Server server) : base(serializer, deserializer)
         {
             this.server = GrpcPreconditions.CheckNotNull(server);
         }
 
-        public void Initialize(CallSafeHandle call)
+        public void Initialize(CallSafeHandle call, CompletionQueueSafeHandle completionQueue)
         {
-            call.Initialize(environment.CompletionRegistry, environment.CompletionQueue);
+            call.Initialize(completionQueue);
 
             server.AddCallReference(this);
             InitializeInternal(call);
@@ -91,11 +91,10 @@
 
         /// <summary>
         /// Sends a streaming response. Only one pending send action is allowed at any given time.
-        /// completionDelegate is called when the operation finishes.
         /// </summary>
-        public void StartSendMessage(TResponse msg, WriteFlags writeFlags, AsyncCompletionDelegate<object> completionDelegate)
+        public Task SendMessageAsync(TResponse msg, WriteFlags writeFlags)
         {
-            StartSendMessageInternal(msg, writeFlags, completionDelegate);
+            return SendMessageInternalAsync(msg, writeFlags);
         }
 
         /// <summary>
@@ -110,20 +109,22 @@
         /// Initiates sending a initial metadata. 
         /// Even though C-core allows sending metadata in parallel to sending messages, we will treat sending metadata as a send message operation
         /// to make things simpler.
-        /// completionDelegate is invoked upon completion.
         /// </summary>
-        public void StartSendInitialMetadata(Metadata headers, AsyncCompletionDelegate<object> completionDelegate)
+        public Task SendInitialMetadataAsync(Metadata headers)
         {
             lock (myLock)
             {
                 GrpcPreconditions.CheckNotNull(headers, "metadata");
-                GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
 
+                GrpcPreconditions.CheckState(started);
                 GrpcPreconditions.CheckState(!initialMetadataSent, "Response headers can only be sent once per call.");
                 GrpcPreconditions.CheckState(streamingWritesCounter == 0, "Response headers can only be sent before the first write starts.");
-                CheckSendingAllowed(allowFinished: false);
 
-                GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
+                var earlyResult = CheckSendAllowedOrEarlyResult();
+                if (earlyResult != null)
+                {
+                    return earlyResult;
+                }
 
                 using (var metadataArray = MetadataArraySafeHandle.Create(headers))
                 {
@@ -131,7 +132,8 @@
                 }
 
                 this.initialMetadataSent = true;
-                sendCompletionDelegate = completionDelegate;
+                streamingWriteTcs = new TaskCompletionSource<object>();
+                return streamingWriteTcs.Task;
             }
         }
 
@@ -196,6 +198,16 @@
             server.RemoveCallReference(this);
         }
 
+        protected override Task CheckSendAllowedOrEarlyResult()
+        {
+            GrpcPreconditions.CheckState(!halfcloseRequested, "Response stream has already been completed.");
+            GrpcPreconditions.CheckState(!finished, "Already finished.");
+            GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time");
+            GrpcPreconditions.CheckState(!disposed);
+
+            return null;
+        }
+
         /// <summary>
         /// Handles the server side close completion.
         /// </summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
deleted file mode 100644
index 7e86fdd..0000000
--- a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-#region Copyright notice and license
-
-// Copyright 2015, 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.
-
-#endregion
-
-using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Threading.Tasks;
-using Grpc.Core.Internal;
-using Grpc.Core.Utils;
-
-namespace Grpc.Core.Internal
-{
-    /// <summary>
-    /// If error != null, there's been an error or operation has been cancelled.
-    /// </summary>
-    internal delegate void AsyncCompletionDelegate<T>(T result, Exception error);
-
-    /// <summary>
-    /// Helper for transforming AsyncCompletionDelegate into full-fledged Task.
-    /// </summary>
-    internal class AsyncCompletionTaskSource<T>
-    {
-        readonly TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
-        readonly AsyncCompletionDelegate<T> completionDelegate;
-
-        public AsyncCompletionTaskSource()
-        {
-            completionDelegate = new AsyncCompletionDelegate<T>(HandleCompletion);
-        }
-
-        public Task<T> Task
-        {
-            get
-            {
-                return tcs.Task;
-            }
-        }
-
-        public AsyncCompletionDelegate<T> CompletionDelegate
-        {
-            get
-            {
-                return completionDelegate;
-            }
-        }
-
-        private void HandleCompletion(T value, Exception error)
-        {
-            if (error == null)
-            {
-                tcs.SetResult(value);
-                return;
-            }
-            if (error is OperationCanceledException)
-            {
-                tcs.SetCanceled();
-                return;
-            }
-            tcs.SetException(error);
-        }
-    }
-}
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index 66d2a66..c28a6f6 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -120,107 +120,4 @@
             return true;
         }
     }
-
-    /// <summary>
-    /// Status + metadata received on client side when call finishes.
-    /// (when receive_status_on_client operation finishes).
-    /// </summary>
-    internal struct ClientSideStatus
-    {
-        readonly Status status;
-        readonly Metadata trailers;
-
-        public ClientSideStatus(Status status, Metadata trailers)
-        {
-            this.status = status;
-            this.trailers = trailers;
-        }
-
-        public Status Status
-        {
-            get
-            {
-                return this.status;
-            }    
-        }
-
-        public Metadata Trailers
-        {
-            get
-            {
-                return this.trailers;
-            }
-        }
-    }
-
-    /// <summary>
-    /// Details of a newly received RPC.
-    /// </summary>
-    internal struct ServerRpcNew
-    {
-        readonly Server server;
-        readonly CallSafeHandle call;
-        readonly string method;
-        readonly string host;
-        readonly Timespec deadline;
-        readonly Metadata requestMetadata;
-
-        public ServerRpcNew(Server server, CallSafeHandle call, string method, string host, Timespec deadline, Metadata requestMetadata)
-        {
-            this.server = server;
-            this.call = call;
-            this.method = method;
-            this.host = host;
-            this.deadline = deadline;
-            this.requestMetadata = requestMetadata;
-        }
-
-        public Server Server
-        {
-            get
-            {
-                return this.server;
-            }
-        }
-
-        public CallSafeHandle Call
-        {
-            get
-            {
-                return this.call;
-            }
-        }
-
-        public string Method
-        {
-            get
-            {
-                return this.method;
-            }
-        }
-
-        public string Host
-        {
-            get
-            {
-                return this.host;
-            }
-        }
-
-        public Timespec Deadline
-        {
-            get
-            {
-                return this.deadline;
-            }
-        }
-
-        public Metadata RequestMetadata
-        {
-            get
-            {
-                return this.requestMetadata;
-            }
-        }
-    }
 }
diff --git a/src/csharp/Grpc.Core/Internal/CallError.cs b/src/csharp/Grpc.Core/Internal/CallError.cs
new file mode 100644
index 0000000..541575f
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/CallError.cs
@@ -0,0 +1,78 @@
+#region Copyright notice and license
+
+// Copyright 2015, 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.
+
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// grpc_call_error from grpc/grpc.h
+    /// </summary>
+    internal enum CallError
+    {
+        /* everything went ok */
+        OK = 0,
+        /* something failed, we don't know what */
+        Error,
+        /* this method is not available on the server */
+        NotOnServer,
+        /* this method is not available on the client */
+        NotOnClient,
+        /* this method must be called before server_accept */
+        AlreadyAccepted,
+        /* this method must be called before invoke */
+        AlreadyInvoked,
+        /* this method must be called after invoke */
+        NotInvoked,
+        /* this call is already finished
+     (writes_done or write_status has already been called) */
+        AlreadyFinished,
+        /* there is already an outstanding read/write operation on the call */
+        TooManyOperations,
+        /* the flags value was illegal for this call */
+        InvalidFlags
+    }
+
+    internal static class CallErrorExtensions
+    {
+        /// <summary>
+        /// Checks the call API invocation's result is OK.
+        /// </summary>
+        public static void CheckOk(this CallError callError)
+        {
+            GrpcPreconditions.CheckState(callError == CallError.OK, "Call error: " + callError);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 244b97d..82361f5 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -47,16 +47,14 @@
         static readonly NativeMethods Native = NativeMethods.Get();
 
         const uint GRPC_WRITE_BUFFER_HINT = 1;
-        CompletionRegistry completionRegistry;
         CompletionQueueSafeHandle completionQueue;
 
         private CallSafeHandle()
         {
         }
 
-        public void Initialize(CompletionRegistry completionRegistry, CompletionQueueSafeHandle completionQueue)
+        public void Initialize(CompletionQueueSafeHandle completionQueue)
         {
-            this.completionRegistry = completionRegistry;
             this.completionQueue = completionQueue;
         }
 
@@ -70,7 +68,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
                 Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags)
                     .CheckOk();
             }
@@ -90,7 +88,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
                 Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk();
             }
         }
@@ -100,7 +98,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
                 Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags).CheckOk();
             }
         }
@@ -110,7 +108,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
                 Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk();
             }
         }
@@ -120,7 +118,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk();
             }
         }
@@ -130,7 +128,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 Native.grpcsharp_call_send_close_from_client(this, ctx).CheckOk();
             }
         }
@@ -142,7 +140,7 @@
             {
                 var ctx = BatchContextSafeHandle.Create();
                 var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata,
                     optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
             }
@@ -153,7 +151,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedMessage()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedMessage()));
                 Native.grpcsharp_call_recv_message(this, ctx).CheckOk();
             }
         }
@@ -163,7 +161,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedInitialMetadata()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedInitialMetadata()));
                 Native.grpcsharp_call_recv_initial_metadata(this, ctx).CheckOk();
             }
         }
@@ -173,7 +171,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedCloseOnServerCancelled()));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedCloseOnServerCancelled()));
                 Native.grpcsharp_call_start_serverside(this, ctx).CheckOk();
             }
         }
@@ -183,7 +181,7 @@
             using (completionQueue.NewScope())
             {
                 var ctx = BatchContextSafeHandle.Create();
-                completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
+                completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 Native.grpcsharp_call_send_initial_metadata(this, ctx, metadataArray).CheckOk();
             }
         }
diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
index 1dbd1f4..62864df 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
@@ -63,7 +63,7 @@
             return Native.grpcsharp_secure_channel_create(credentials, target, channelArgs);
         }
 
-        public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials)
+        public CallSafeHandle CreateCall(CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials)
         {
             using (Profilers.ForCurrentThread().NewScope("ChannelSafeHandle.CreateCall"))
             {
@@ -72,7 +72,7 @@
                 {
                     result.SetCredentials(credentials);
                 }
-                result.Initialize(registry, cq);
+                result.Initialize(cq);
                 return result;
             }
         }
@@ -82,11 +82,10 @@
             return Native.grpcsharp_channel_check_connectivity_state(this, tryToConnect ? 1 : 0);
         }
 
-        public void WatchConnectivityState(ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq,
-            CompletionRegistry completionRegistry, BatchCompletionDelegate callback)
+        public void WatchConnectivityState(ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchCompletionDelegate callback)
         {
             var ctx = BatchContextSafeHandle.Create();
-            completionRegistry.RegisterBatchCompletion(ctx, callback);
+            cq.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
             Native.grpcsharp_channel_watch_connectivity_state(this, lastObservedState, deadline, cq, ctx);
         }
 
diff --git a/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
index 013f00f..924de02 100644
--- a/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs
@@ -50,16 +50,12 @@
 
         public Task WriteAsync(TRequest message)
         {
-            var taskSource = new AsyncCompletionTaskSource<object>();
-            call.StartSendMessage(message, GetWriteFlags(), taskSource.CompletionDelegate);
-            return taskSource.Task;
+            return call.SendMessageAsync(message, GetWriteFlags());
         }
 
         public Task CompleteAsync()
         {
-            var taskSource = new AsyncCompletionTaskSource<object>();
-            call.StartSendCloseFromClient(taskSource.CompletionDelegate);
-            return taskSource.Task;
+            return call.SendCloseFromClientAsync();
         }
 
         public WriteOptions WriteOptions
diff --git a/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs b/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs
new file mode 100644
index 0000000..5727e3f
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs
@@ -0,0 +1,70 @@
+#region Copyright notice and license
+
+// Copyright 2015, 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.
+
+#endregion
+
+using System;
+using Grpc.Core;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// Status + metadata received on client side when call finishes.
+    /// (when receive_status_on_client operation finishes).
+    /// </summary>
+    internal struct ClientSideStatus
+    {
+        readonly Status status;
+        readonly Metadata trailers;
+
+        public ClientSideStatus(Status status, Metadata trailers)
+        {
+            this.status = status;
+            this.trailers = trailers;
+        }
+
+        public Status Status
+        {
+            get
+            {
+                return this.status;
+            }
+        }
+
+        public Metadata Trailers
+        {
+            get
+            {
+                return this.trailers;
+            }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/ClockType.cs b/src/csharp/Grpc.Core/Internal/ClockType.cs
new file mode 100644
index 0000000..57533c9
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ClockType.cs
@@ -0,0 +1,53 @@
+#region Copyright notice and license
+
+// Copyright 2015, 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.
+
+#endregion
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// gpr_clock_type from grpc/support/time.h
+    /// </summary>
+    internal enum ClockType
+    {
+        /* Monotonic clock */
+        Monotonic,
+
+        /* Realtime clock */
+        Realtime,
+
+        /* Precise clock good for performance profiling. */
+        Precise,
+
+        /* Timespan - the distance between two time points */
+        Timespan
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
index 2886807..a78e9b7 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs
@@ -44,7 +44,7 @@
     {
         static readonly NativeMethods Native = NativeMethods.Get();
 
-        public GRPCCompletionType type;
+        public CompletionType type;
         public int success;
         public IntPtr tag;
 
@@ -55,5 +55,20 @@
                 return Native.grpcsharp_sizeof_grpc_event();
             }
         }
+
+        /// <summary>
+        /// grpc_completion_type from grpc/grpc.h
+        /// </summary>
+        internal enum CompletionType
+        {
+            /* Shutting down */
+            Shutdown, 
+
+            /* No event before timeout */
+            Timeout,  
+
+            /* operation completion */
+            OpComplete
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
index 91364cd..46f5624 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
@@ -45,6 +45,7 @@
         static readonly NativeMethods Native = NativeMethods.Get();
 
         AtomicCounter shutdownRefcount = new AtomicCounter(1);
+        CompletionRegistry completionRegistry;
 
         private CompletionQueueSafeHandle()
         {
@@ -53,7 +54,13 @@
         public static CompletionQueueSafeHandle Create()
         {
             return Native.grpcsharp_completion_queue_create();
+        }
 
+        public static CompletionQueueSafeHandle Create(CompletionRegistry completionRegistry)
+        {
+            var cq = Native.grpcsharp_completion_queue_create();
+            cq.completionRegistry = completionRegistry;
+            return cq;
         }
 
         public CompletionQueueEvent Next()
@@ -83,6 +90,15 @@
             DecrementShutdownRefcount();
         }
 
+        /// <summary>
+        /// Completion registry associated with this completion queue.
+        /// Doesn't need to be set if only using Pluck() operations.
+        /// </summary>
+        public CompletionRegistry CompletionRegistry
+        {
+            get { return completionRegistry; }
+        }
+
         protected override bool ReleaseHandle()
         {
             Native.grpcsharp_completion_queue_destroy(handle);
diff --git a/src/csharp/Grpc.Core/Internal/Enums.cs b/src/csharp/Grpc.Core/Internal/Enums.cs
deleted file mode 100644
index 74f86d2..0000000
--- a/src/csharp/Grpc.Core/Internal/Enums.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-#region Copyright notice and license
-
-// Copyright 2015, 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.
-
-#endregion
-
-using System;
-using System.Runtime.InteropServices;
-using Grpc.Core.Utils;
-
-namespace Grpc.Core.Internal
-{
-    /// <summary>
-    /// grpc_call_error from grpc/grpc.h
-    /// </summary>
-    internal enum GRPCCallError
-    {
-        /* everything went ok */
-        OK = 0,
-        /* something failed, we don't know what */
-        Error,
-        /* this method is not available on the server */
-        NotOnServer,
-        /* this method is not available on the client */
-        NotOnClient,
-        /* this method must be called before server_accept */
-        AlreadyAccepted,
-        /* this method must be called before invoke */
-        AlreadyInvoked,
-        /* this method must be called after invoke */
-        NotInvoked,
-        /* this call is already finished
-     (writes_done or write_status has already been called) */
-        AlreadyFinished,
-        /* there is already an outstanding read/write operation on the call */
-        TooManyOperations,
-        /* the flags value was illegal for this call */
-        InvalidFlags
-    }
-
-    internal static class CallErrorExtensions
-    {
-        /// <summary>
-        /// Checks the call API invocation's result is OK.
-        /// </summary>
-        public static void CheckOk(this GRPCCallError callError)
-        {
-            GrpcPreconditions.CheckState(callError == GRPCCallError.OK, "Call error: " + callError);
-        }
-    }
-
-    /// <summary>
-    /// grpc_completion_type from grpc/grpc.h
-    /// </summary>
-    internal enum GRPCCompletionType
-    {
-        /* Shutting down */
-        Shutdown, 
-
-        /* No event before timeout */
-        Timeout,  
-
-        /* operation completion */
-        OpComplete
-    }
-
-    /// <summary>
-    /// gpr_clock_type from grpc/support/time.h
-    /// </summary>
-    internal enum GPRClockType
-    {
-        /* Monotonic clock */
-        Monotonic,
-
-        /* Realtime clock */
-        Realtime,
-
-        /* Precise clock good for performance profiling. */
-        Precise,
-
-        /* Timespan - the distance between two time points */
-        Timespan
-    }
-}
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index 4b7124e..4de543b 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -33,15 +33,15 @@
 
 using System;
 using System.Collections.Generic;
-using System.Runtime.InteropServices;
+using System.Linq;
 using System.Threading;
-using System.Threading.Tasks;
 using Grpc.Core.Logging;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core.Internal
 {
     /// <summary>
-    /// Pool of threads polling on the same completion queue.
+    /// Pool of threads polling on a set of completions queues.
     /// </summary>
     internal class GrpcThreadPool
     {
@@ -51,25 +51,31 @@
         readonly object myLock = new object();
         readonly List<Thread> threads = new List<Thread>();
         readonly int poolSize;
+        readonly int completionQueueCount;
 
-        CompletionQueueSafeHandle cq;
+        IReadOnlyCollection<CompletionQueueSafeHandle> completionQueues;
 
-        public GrpcThreadPool(GrpcEnvironment environment, int poolSize)
+        /// <summary>
+        /// Creates a thread pool threads polling on a set of completions queues.
+        /// </summary>
+        /// <param name="environment">Environment.</param>
+        /// <param name="poolSize">Pool size.</param>
+        /// <param name="completionQueueCount">Completion queue count.</param>
+        public GrpcThreadPool(GrpcEnvironment environment, int poolSize, int completionQueueCount)
         {
             this.environment = environment;
             this.poolSize = poolSize;
+            this.completionQueueCount = completionQueueCount;
+            GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount,
+                "Thread pool size cannot be smaller than the number of completion queues used.");
         }
 
         public void Start()
         {
             lock (myLock)
             {
-                if (cq != null)
-                {
-                    throw new InvalidOperationException("Already started.");
-                }
-
-                cq = CompletionQueueSafeHandle.Create();
+                GrpcPreconditions.CheckState(completionQueues == null, "Already started.");
+                completionQueues = CreateCompletionQueueList(environment, completionQueueCount);
 
                 for (int i = 0; i < poolSize; i++)
                 {
@@ -82,49 +88,60 @@
         {
             lock (myLock)
             {
-                cq.Shutdown();
+                foreach (var cq in completionQueues)
+                {
+                    cq.Shutdown();
+                }
+
                 foreach (var thread in threads)
                 {
                     thread.Join();
                 }
 
-                cq.Dispose();
+                foreach (var cq in completionQueues)
+                {
+                    cq.Dispose();
+                }
             }
         }
 
-        internal CompletionQueueSafeHandle CompletionQueue
+        internal IReadOnlyCollection<CompletionQueueSafeHandle> CompletionQueues
         {
             get
             {
-                return cq;
+                return completionQueues;
             }
         }
 
-        private Thread CreateAndStartThread(int i)
+        private Thread CreateAndStartThread(int threadIndex)
         {
-            var thread = new Thread(new ThreadStart(RunHandlerLoop));
+            var cqIndex = threadIndex % completionQueues.Count;
+            var cq = completionQueues.ElementAt(cqIndex);
+
+            var thread = new Thread(new ThreadStart(() => RunHandlerLoop(cq)));
             thread.IsBackground = false;
+            thread.Name = string.Format("grpc {0} (cq {1})", threadIndex, cqIndex);
             thread.Start();
-            thread.Name = "grpc " + i;
+
             return thread;
         }
 
         /// <summary>
         /// Body of the polling thread.
         /// </summary>
-        private void RunHandlerLoop()
+        private void RunHandlerLoop(CompletionQueueSafeHandle cq)
         {
             CompletionQueueEvent ev;
             do
             {
                 ev = cq.Next();
-                if (ev.type == GRPCCompletionType.OpComplete)
+                if (ev.type == CompletionQueueEvent.CompletionType.OpComplete)
                 {
                     bool success = (ev.success != 0);
                     IntPtr tag = ev.tag;
                     try
                     {
-                        var callback = environment.CompletionRegistry.Extract(tag);
+                        var callback = cq.CompletionRegistry.Extract(tag);
                         callback(success);
                     }
                     catch (Exception e)
@@ -133,7 +150,18 @@
                     }
                 }
             }
-            while (ev.type != GRPCCompletionType.Shutdown);
+            while (ev.type != CompletionQueueEvent.CompletionType.Shutdown);
+        }
+
+        private static IReadOnlyCollection<CompletionQueueSafeHandle> CreateCompletionQueueList(GrpcEnvironment environment, int completionQueueCount)
+        {
+            var list = new List<CompletionQueueSafeHandle>();
+            for (int i = 0; i < completionQueueCount; i++)
+            {
+                var completionRegistry = new CompletionRegistry(environment);
+                list.Add(CompletionQueueSafeHandle.Create(completionRegistry));
+            }
+            return list.AsReadOnly();
         }
     }
 }
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
index 25735d5..dc9f62f 100644
--- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -50,6 +50,11 @@
         {
             using (Profilers.ForCurrentThread().NewScope("MetadataArraySafeHandle.Create"))
             {
+                if (metadata.Count == 0)
+                {
+                    return new MetadataArraySafeHandle();
+                }
+
                 // TODO(jtattermusch): we might wanna check that the metadata is readonly 
                 var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count));
                 for (int i = 0; i < metadata.Count; i++)
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index c277c73..65607ed 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -137,6 +137,7 @@
         public readonly Delegates.grpcsharp_server_credentials_release_delegate grpcsharp_server_credentials_release;
 
         public readonly Delegates.grpcsharp_server_create_delegate grpcsharp_server_create;
+        public readonly Delegates.grpcsharp_server_register_completion_queue_delegate grpcsharp_server_register_completion_queue;
         public readonly Delegates.grpcsharp_server_add_insecure_http2_port_delegate grpcsharp_server_add_insecure_http2_port;
         public readonly Delegates.grpcsharp_server_add_secure_http2_port_delegate grpcsharp_server_add_secure_http2_port;
         public readonly Delegates.grpcsharp_server_start_delegate grpcsharp_server_start;
@@ -244,6 +245,7 @@
                 this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library);
 
                 this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library);
+                this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library);
                 this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library);
                 this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library);
                 this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library);
@@ -348,6 +350,7 @@
                 this.grpcsharp_server_credentials_release = PInvokeMethods.grpcsharp_server_credentials_release;
 
                 this.grpcsharp_server_create = PInvokeMethods.grpcsharp_server_create;
+                this.grpcsharp_server_register_completion_queue = PInvokeMethods.grpcsharp_server_register_completion_queue;
                 this.grpcsharp_server_add_insecure_http2_port = PInvokeMethods.grpcsharp_server_add_insecure_http2_port;
                 this.grpcsharp_server_add_secure_http2_port = PInvokeMethods.grpcsharp_server_add_secure_http2_port;
                 this.grpcsharp_server_start = PInvokeMethods.grpcsharp_server_start;
@@ -418,33 +421,33 @@
             public delegate CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create_delegate(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2);
             public delegate void grpcsharp_call_credentials_release_delegate(IntPtr credentials);
 
-            public delegate GRPCCallError grpcsharp_call_cancel_delegate(CallSafeHandle call);
-            public delegate GRPCCallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description);
-            public delegate GRPCCallError grpcsharp_call_start_unary_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_cancel_delegate(CallSafeHandle call);
+            public delegate CallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description);
+            public delegate CallError grpcsharp_call_start_unary_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
-            public delegate GRPCCallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-            public delegate GRPCCallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen,
                 MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
-            public delegate GRPCCallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-            public delegate GRPCCallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
-            public delegate GRPCCallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
-            public delegate GRPCCallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
                 byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
-            public delegate GRPCCallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
-            public delegate GRPCCallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
-            public delegate GRPCCallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
-            public delegate GRPCCallError grpcsharp_call_send_initial_metadata_delegate(CallSafeHandle call,
+            public delegate CallError grpcsharp_call_send_initial_metadata_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
-            public delegate GRPCCallError grpcsharp_call_set_credentials_delegate(CallSafeHandle call, CallCredentialsSafeHandle credentials);
+            public delegate CallError grpcsharp_call_set_credentials_delegate(CallSafeHandle call, CallCredentialsSafeHandle credentials);
             public delegate CStringSafeHandle grpcsharp_call_get_peer_delegate(CallSafeHandle call);
             public delegate void grpcsharp_call_destroy_delegate(IntPtr call);
 
@@ -493,23 +496,24 @@
             public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth);
             public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials);
 
-            public delegate ServerSafeHandle grpcsharp_server_create_delegate(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args);
+            public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args);
+            public delegate void grpcsharp_server_register_completion_queue_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq);
             public delegate int grpcsharp_server_add_insecure_http2_port_delegate(ServerSafeHandle server, string addr);
             public delegate int grpcsharp_server_add_secure_http2_port_delegate(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
             public delegate void grpcsharp_server_start_delegate(ServerSafeHandle server);
-            public delegate GRPCCallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
+            public delegate CallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
             public delegate void grpcsharp_server_cancel_all_calls_delegate(ServerSafeHandle server);
             public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
             public delegate void grpcsharp_server_destroy_delegate(IntPtr server);
 
-            public delegate Timespec gprsharp_now_delegate(GPRClockType clockType);
-            public delegate Timespec gprsharp_inf_future_delegate(GPRClockType clockType);
-            public delegate Timespec gprsharp_inf_past_delegate(GPRClockType clockType);
+            public delegate Timespec gprsharp_now_delegate(ClockType clockType);
+            public delegate Timespec gprsharp_inf_future_delegate(ClockType clockType);
+            public delegate Timespec gprsharp_inf_past_delegate(ClockType clockType);
 
-            public delegate Timespec gprsharp_convert_clock_type_delegate(Timespec t, GPRClockType targetClock);
+            public delegate Timespec gprsharp_convert_clock_type_delegate(Timespec t, ClockType targetClock);
             public delegate int gprsharp_sizeof_timespec_delegate();
 
-            public delegate GRPCCallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
+            public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
             public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr);
         }
 
@@ -587,59 +591,59 @@
             // CallSafeHandle
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_cancel(CallSafeHandle call);
+            public static extern CallError grpcsharp_call_cancel(CallSafeHandle call);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description);
+            public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen,
                 MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_send_message(CallSafeHandle call,
                 BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call,
                 BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
                 byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_start_serverside(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_send_initial_metadata(CallSafeHandle call,
+            public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials);
+            public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials);
 
             [DllImport("grpc_csharp_ext.dll")]
             public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call);
@@ -773,7 +777,10 @@
             // ServerSafeHandle
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern ServerSafeHandle grpcsharp_server_create(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args);
+            public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args);
+
+            [DllImport("grpc_csharp_ext.dll")]
+            public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq);
 
             [DllImport("grpc_csharp_ext.dll")]
             public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr);
@@ -785,7 +792,7 @@
             public static extern void grpcsharp_server_start(ServerSafeHandle server);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
+            public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
 
             [DllImport("grpc_csharp_ext.dll")]
             public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server);
@@ -799,16 +806,16 @@
             // Timespec
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern Timespec gprsharp_now(GPRClockType clockType);
+            public static extern Timespec gprsharp_now(ClockType clockType);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern Timespec gprsharp_inf_future(GPRClockType clockType);
+            public static extern Timespec gprsharp_inf_future(ClockType clockType);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern Timespec gprsharp_inf_past(GPRClockType clockType);
+            public static extern Timespec gprsharp_inf_past(ClockType clockType);
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern Timespec gprsharp_convert_clock_type(Timespec t, GPRClockType targetClock);
+            public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock);
 
             [DllImport("grpc_csharp_ext.dll")]
             public static extern int gprsharp_sizeof_timespec();
@@ -816,7 +823,7 @@
             // Testing
 
             [DllImport("grpc_csharp_ext.dll")]
-            public static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
+            public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
 
             [DllImport("grpc_csharp_ext.dll")]
             public static extern IntPtr grpcsharp_test_nop(IntPtr ptr);
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 85b7a4b..6a2f520 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -44,7 +44,7 @@
 {
     internal interface IServerCallHandler
     {
-        Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment);
+        Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq);
     }
 
     internal class UnaryServerCallHandler<TRequest, TResponse> : IServerCallHandler
@@ -62,14 +62,14 @@
             this.handler = handler;
         }
 
-        public async Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment)
+        public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
                 method.ResponseMarshaller.Serializer,
                 method.RequestMarshaller.Deserializer,
-                environment, newRpc.Server);
+                newRpc.Server);
 
-            asyncCall.Initialize(newRpc.Call);
+            asyncCall.Initialize(newRpc.Call, cq);
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
@@ -121,14 +121,14 @@
             this.handler = handler;
         }
 
-        public async Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment)
+        public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
                 method.ResponseMarshaller.Serializer,
                 method.RequestMarshaller.Deserializer,
-                environment, newRpc.Server);
+                newRpc.Server);
 
-            asyncCall.Initialize(newRpc.Call);
+            asyncCall.Initialize(newRpc.Call, cq);
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
@@ -179,14 +179,14 @@
             this.handler = handler;
         }
 
-        public async Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment)
+        public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
                 method.ResponseMarshaller.Serializer,
                 method.RequestMarshaller.Deserializer,
-                environment, newRpc.Server);
+                newRpc.Server);
 
-            asyncCall.Initialize(newRpc.Call);
+            asyncCall.Initialize(newRpc.Call, cq);
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
@@ -237,14 +237,14 @@
             this.handler = handler;
         }
 
-        public async Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment)
+        public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
                 method.ResponseMarshaller.Serializer,
                 method.RequestMarshaller.Deserializer,
-                environment, newRpc.Server);
+                newRpc.Server);
 
-            asyncCall.Initialize(newRpc.Call);
+            asyncCall.Initialize(newRpc.Call, cq);
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
@@ -281,13 +281,13 @@
     {
         public static readonly NoSuchMethodCallHandler Instance = new NoSuchMethodCallHandler();
 
-        public async Task HandleCall(ServerRpcNew newRpc, GrpcEnvironment environment)
+        public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             // We don't care about the payload type here.
             var asyncCall = new AsyncCallServer<byte[], byte[]>(
-                (payload) => payload, (payload) => payload, environment, newRpc.Server);
+                (payload) => payload, (payload) => payload, newRpc.Server);
             
-            asyncCall.Initialize(newRpc.Call);
+            asyncCall.Initialize(newRpc.Call, cq);
             var finishedTask = asyncCall.ServerSideCallAsync();
             await asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, ""), Metadata.Empty, null).ConfigureAwait(false);
             await finishedTask.ConfigureAwait(false);
@@ -317,7 +317,7 @@
             where TRequest : class
             where TResponse : class
         {
-            DateTime realtimeDeadline = newRpc.Deadline.ToClockType(GPRClockType.Realtime).ToDateTime();
+            DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime();
 
             return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, peer, realtimeDeadline,
                 newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream);
diff --git a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
index ecfee0b..25b79b4 100644
--- a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
@@ -52,16 +52,12 @@
 
         public Task WriteAsync(TResponse message)
         {
-            var taskSource = new AsyncCompletionTaskSource<object>();
-            call.StartSendMessage(message, GetWriteFlags(), taskSource.CompletionDelegate);
-            return taskSource.Task;
+            return call.SendMessageAsync(message, GetWriteFlags());
         }
 
         public Task WriteResponseHeadersAsync(Metadata responseHeaders)
         {
-            var taskSource = new AsyncCompletionTaskSource<object>();
-            call.StartSendInitialMetadata(responseHeaders, taskSource.CompletionDelegate);
-            return taskSource.Task;
+            return call.SendInitialMetadataAsync(responseHeaders);
         }
 
         public WriteOptions WriteOptions
diff --git a/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs b/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs
new file mode 100644
index 0000000..e4f1880
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs
@@ -0,0 +1,109 @@
+#region Copyright notice and license
+
+// Copyright 2015, 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.
+
+#endregion
+
+using System;
+using Grpc.Core;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// Details of a newly received RPC.
+    /// </summary>
+    internal struct ServerRpcNew
+    {
+        readonly Server server;
+        readonly CallSafeHandle call;
+        readonly string method;
+        readonly string host;
+        readonly Timespec deadline;
+        readonly Metadata requestMetadata;
+
+        public ServerRpcNew(Server server, CallSafeHandle call, string method, string host, Timespec deadline, Metadata requestMetadata)
+        {
+            this.server = server;
+            this.call = call;
+            this.method = method;
+            this.host = host;
+            this.deadline = deadline;
+            this.requestMetadata = requestMetadata;
+        }
+
+        public Server Server
+        {
+            get
+            {
+                return this.server;
+            }
+        }
+
+        public CallSafeHandle Call
+        {
+            get
+            {
+                return this.call;
+            }
+        }
+
+        public string Method
+        {
+            get
+            {
+                return this.method;
+            }
+        }
+
+        public string Host
+        {
+            get
+            {
+                return this.host;
+            }
+        }
+
+        public Timespec Deadline
+        {
+            get
+            {
+                return this.deadline;
+            }
+        }
+
+        public Metadata RequestMetadata
+        {
+            get
+            {
+                return this.requestMetadata;
+            }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index 6b5f70e..8581302 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -31,12 +31,6 @@
 
 #endregion
 
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using Grpc.Core.Utils;
-
 namespace Grpc.Core.Internal
 {
     /// <summary>
@@ -50,12 +44,17 @@
         {
         }
 
-        public static ServerSafeHandle NewServer(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args)
+        public static ServerSafeHandle NewServer(ChannelArgsSafeHandle args)
         {
             // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle.
             // Doing so would make object finalizer crash if we end up abandoning the handle.
             GrpcEnvironment.GrpcNativeInit();
-            return Native.grpcsharp_server_create(cq, args);
+            return Native.grpcsharp_server_create(args);
+        }
+
+        public void RegisterCompletionQueue(CompletionQueueSafeHandle cq)
+        {
+            Native.grpcsharp_server_register_completion_queue(this, cq);
         }
 
         public int AddInsecurePort(string addr)
@@ -73,18 +72,18 @@
             Native.grpcsharp_server_start(this);
         }
     
-        public void ShutdownAndNotify(BatchCompletionDelegate callback, GrpcEnvironment environment)
+        public void ShutdownAndNotify(BatchCompletionDelegate callback, CompletionQueueSafeHandle completionQueue)
         {
             var ctx = BatchContextSafeHandle.Create();
-            environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
-            Native.grpcsharp_server_shutdown_and_notify_callback(this, environment.CompletionQueue, ctx);
+            completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+            Native.grpcsharp_server_shutdown_and_notify_callback(this, completionQueue, ctx);
         }
 
-        public void RequestCall(BatchCompletionDelegate callback, GrpcEnvironment environment)
+        public void RequestCall(BatchCompletionDelegate callback, CompletionQueueSafeHandle completionQueue)
         {
             var ctx = BatchContextSafeHandle.Create();
-            environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
-            Native.grpcsharp_server_request_call(this, environment.CompletionQueue, ctx).CheckOk();
+            completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
+            Native.grpcsharp_server_request_call(this, completionQueue, ctx).CheckOk();
         }
 
         protected override bool ReleaseHandle()
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index 56172a5..c9fd710 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -49,11 +49,11 @@
         static readonly NativeMethods Native = NativeMethods.Get();
         static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 
-        public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, GPRClockType.Realtime)
+        public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, ClockType.Realtime)
         {
         }
 
-        public Timespec(long tv_sec, int tv_nsec, GPRClockType clock_type)
+        public Timespec(long tv_sec, int tv_nsec, ClockType clock_type)
         {
             this.tv_sec = tv_sec;
             this.tv_nsec = tv_nsec;
@@ -62,7 +62,7 @@
 
         private long tv_sec;
         private int tv_nsec;
-        private GPRClockType clock_type;
+        private ClockType clock_type;
 
         /// <summary>
         /// Timespec a long time in the future.
@@ -71,7 +71,7 @@
         {
             get
             {
-                return Native.gprsharp_inf_future(GPRClockType.Realtime);
+                return new Timespec(long.MaxValue, 0, ClockType.Realtime);
             }
         }
 
@@ -82,7 +82,7 @@
         {
             get
             {
-                return Native.gprsharp_inf_past(GPRClockType.Realtime);
+                return new Timespec(long.MinValue, 0, ClockType.Realtime);
             }
         }
 
@@ -93,7 +93,7 @@
         {
             get
             {
-                return Native.gprsharp_now(GPRClockType.Realtime);
+                return Native.gprsharp_now(ClockType.Realtime);
             }
         }
 
@@ -122,7 +122,7 @@
         /// <summary>
         /// Converts the timespec to desired clock type.
         /// </summary>
-        public Timespec ToClockType(GPRClockType targetClock)
+        public Timespec ToClockType(ClockType targetClock)
         {
             return Native.gprsharp_convert_clock_type(this, targetClock);
         }
@@ -142,7 +142,7 @@
         public DateTime ToDateTime()
         {
             GrpcPreconditions.CheckState(tv_nsec >= 0 && tv_nsec < NanosPerSecond);
-            GrpcPreconditions.CheckState(clock_type == GPRClockType.Realtime);
+            GrpcPreconditions.CheckState(clock_type == ClockType.Realtime);
 
             // fast path for InfFuture
             if (this.Equals(InfFuture))
@@ -227,10 +227,11 @@
         {
             get
             {
-                return Native.gprsharp_now(GPRClockType.Precise);
+                return Native.gprsharp_now(ClockType.Precise);
             }
         }
 
+        // for tests only
         internal static int NativeSize
         {
             get
@@ -238,5 +239,23 @@
                 return Native.gprsharp_sizeof_timespec();
             }
         }
+
+        // for tests only
+        internal static Timespec NativeInfFuture
+        {
+            get
+            {
+                return Native.gprsharp_inf_future(ClockType.Realtime);
+            }
+        }
+
+        // for tests only
+        public static Timespec NativeInfPast
+        {
+            get
+            {
+                return Native.gprsharp_inf_past(ClockType.Realtime);
+            }
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index bde7494..370fa98 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -16,6 +16,12 @@
     "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
     "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
     "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
+[assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" +
+    "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
+    "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
+    "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
+    "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
 #else
 [assembly: InternalsVisibleTo("Grpc.Core.Tests")]
+[assembly: InternalsVisibleTo("Grpc.IntegrationTesting")]
 #endif
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index d538a46..069185e 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -34,8 +34,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
+using System.Linq;
 using System.Threading.Tasks;
 using Grpc.Core.Internal;
 using Grpc.Core.Logging;
@@ -48,7 +47,7 @@
     /// </summary>
     public class Server
     {
-        const int InitialAllowRpcTokenCount = 10;
+        const int InitialAllowRpcTokenCountPerCq = 10;
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<Server>();
 
         readonly AtomicCounter activeCallCounter = new AtomicCounter();
@@ -80,7 +79,12 @@
             this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
             using (var channelArgs = ChannelOptions.CreateChannelArgs(this.options))
             {
-                this.handle = ServerSafeHandle.NewServer(environment.CompletionQueue, channelArgs);
+                this.handle = ServerSafeHandle.NewServer(channelArgs);
+            }
+
+            foreach (var cq in environment.CompletionQueues)
+            {
+                this.handle.RegisterCompletionQueue(cq);
             }
         }
 
@@ -133,9 +137,12 @@
 
                 // Starting with more than one AllowOneRpc tokens can significantly increase
                 // unary RPC throughput.
-                for (int i = 0; i < InitialAllowRpcTokenCount; i++)
+                for (int i = 0; i < InitialAllowRpcTokenCountPerCq; i++)
                 {
-                    AllowOneRpc();
+                    foreach (var cq in environment.CompletionQueues)
+                    {
+                        AllowOneRpc(cq);
+                    }
                 }
             }
         }
@@ -154,7 +161,8 @@
                 shutdownRequested = true;
             }
 
-            handle.ShutdownAndNotify(HandleServerShutdown, environment);
+            var cq = environment.CompletionQueues.First();  // any cq will do
+            handle.ShutdownAndNotify(HandleServerShutdown, cq);
             await shutdownTcs.Task.ConfigureAwait(false);
             DisposeHandle();
 
@@ -174,7 +182,8 @@
                 shutdownRequested = true;
             }
 
-            handle.ShutdownAndNotify(HandleServerShutdown, environment);
+            var cq = environment.CompletionQueues.First();  // any cq will do
+            handle.ShutdownAndNotify(HandleServerShutdown, cq);
             handle.CancelAllCalls();
             await shutdownTcs.Task.ConfigureAwait(false);
             DisposeHandle();
@@ -244,11 +253,11 @@
         /// <summary>
         /// Allows one new RPC call to be received by server.
         /// </summary>
-        private void AllowOneRpc()
+        private void AllowOneRpc(CompletionQueueSafeHandle cq)
         {
             if (!shutdownRequested)
             {
-                handle.RequestCall(HandleNewServerRpc, environment);
+                handle.RequestCall((success, ctx) => HandleNewServerRpc(success, ctx, cq), cq);
             }
         }
 
@@ -265,7 +274,7 @@
         /// <summary>
         /// Selects corresponding handler for given call and handles the call.
         /// </summary>
-        private async Task HandleCallAsync(ServerRpcNew newRpc)
+        private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
             try
             {
@@ -274,7 +283,7 @@
                 {
                     callHandler = NoSuchMethodCallHandler.Instance;
                 }
-                await callHandler.HandleCall(newRpc, environment).ConfigureAwait(false);
+                await callHandler.HandleCall(newRpc, cq).ConfigureAwait(false);
             }
             catch (Exception e)
             {
@@ -285,9 +294,9 @@
         /// <summary>
         /// Handles the native callback.
         /// </summary>
-        private void HandleNewServerRpc(bool success, BatchContextSafeHandle ctx)
+        private void HandleNewServerRpc(bool success, BatchContextSafeHandle ctx, CompletionQueueSafeHandle cq)
         {
-			Task.Run(() => AllowOneRpc());
+			Task.Run(() => AllowOneRpc(cq));
 
             if (success)
             {
@@ -296,7 +305,7 @@
                 // after server shutdown, the callback returns with null call
                 if (!newRpc.Call.IsInvalid)
                 {
-                    HandleCallAsync(newRpc);  // we don't need to await.
+                    HandleCallAsync(newRpc, cq);  // we don't need to await.
                 }
             }
         }
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index cfe668b..3fd28c6 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -37,7 +37,7 @@
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="Google.Protobuf">
-      <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
+      <HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="nunit.framework">
       <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config
index ce030f9..668601a 100644
--- a/src/csharp/Grpc.Examples.Tests/packages.config
+++ b/src/csharp/Grpc.Examples.Tests/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="NUnit" version="3.2.0" targetFramework="net45" />
   <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index f0a0aa3..30170ab 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -39,7 +39,7 @@
   <ItemGroup>
     <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
+      <HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="nunit.framework">
       <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs
index 33c4f8d..a17228c 100644
--- a/src/csharp/Grpc.Examples/Math.cs
+++ b/src/csharp/Grpc.Examples/Math.cs
@@ -34,12 +34,12 @@
             "Mw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Math.DivArgs), global::Math.DivArgs.Parser, new[]{ "Dividend", "Divisor" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Math.DivReply), global::Math.DivReply.Parser, new[]{ "Quotient", "Remainder" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Math.FibArgs), global::Math.FibArgs.Parser, new[]{ "Limit" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Math.Num), global::Math.Num.Parser, new[]{ "Num_" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Math.FibReply), global::Math.FibReply.Parser, new[]{ "Count" }, null, null, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivArgs), global::Math.DivArgs.Parser, new[]{ "Dividend", "Divisor" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivReply), global::Math.DivReply.Parser, new[]{ "Quotient", "Remainder" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibArgs), global::Math.FibArgs.Parser, new[]{ "Limit" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Math.Num), global::Math.Num.Parser, new[]{ "Num_" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibReply), global::Math.FibReply.Parser, new[]{ "Count" }, null, null, null)
           }));
     }
     #endregion
diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config
index a424cd2..a70dcbd 100644
--- a/src/csharp/Grpc.Examples/packages.config
+++ b/src/csharp/Grpc.Examples/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="NUnit" version="3.2.0" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
index 0bea9c0..a5ee4fd 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
+++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
@@ -45,7 +45,7 @@
     <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
     <Reference Include="Google.Protobuf">
-      <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
+      <HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="nunit.framework">
       <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
index fb29294..070674b 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
@@ -79,16 +79,17 @@
         [Test]
         public void ServiceIsRunning()
         {
-            serviceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
+            serviceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving);
 
             var response = client.Check(new HealthCheckRequest { Service = "" });
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, response.Status);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, response.Status);
         }
 
         [Test]
         public void ServiceDoesntExist()
         {
-            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(new HealthCheckRequest { Service = "nonexistent.service" }));
+            var ex = Assert.Throws<RpcException>(() => client.Check(new HealthCheckRequest { Service = "nonexistent.service" }));
+            Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode);
         }
 
         // TODO(jtattermusch): add test with timeout once timeouts are supported
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
index a4b79e3..1570360 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
@@ -50,38 +50,39 @@
         public void SetStatus()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NOT_SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NOT_SERVING, GetStatusHelper(impl, ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NotServing);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Unknown);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "grpc.test.TestService"));
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Serving);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, "grpc.test.TestService"));
         }
 
         [Test]
         public void ClearStatus()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
-            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving);
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown);
 
             impl.ClearStatus("");
 
-            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => GetStatusHelper(impl, ""));
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "grpc.test.TestService"));
+            var ex = Assert.Throws<RpcException>(() => GetStatusHelper(impl, ""));
+            Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, "grpc.test.TestService"));
         }
 
         [Test]
         public void ClearAll()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
-            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving);
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown);
 
             impl.ClearAll();
             Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, ""));
@@ -92,7 +93,7 @@
         public void NullsRejected()
         {
             var impl = new HealthServiceImpl();
-            Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, HealthCheckResponse.Types.ServingStatus.SERVING));
+            Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, HealthCheckResponse.Types.ServingStatus.Serving));
 
             Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus(null));
         }
diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config
index 8066d8f..2bcfec8 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/packages.config
+++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
   <package id="NUnit" version="3.2.0" targetFramework="net45" />
   <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index 498528a..2697b74 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -40,7 +40,7 @@
   <ItemGroup>
     <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
+      <HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
index d0d0c0b..100ad18 100644
--- a/src/csharp/Grpc.HealthCheck/Health.cs
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -33,9 +33,9 @@
             "Ag5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1.HealthCheckRequest), global::Grpc.Health.V1.HealthCheckRequest.Parser, new[]{ "Service" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1.HealthCheckResponse), global::Grpc.Health.V1.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) }, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckRequest), global::Grpc.Health.V1.HealthCheckRequest.Parser, new[]{ "Service" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckResponse), global::Grpc.Health.V1.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) }, null)
           }));
     }
     #endregion
@@ -75,7 +75,7 @@
     public string Service {
       get { return service_; }
       set {
-        service_ = pb::Preconditions.CheckNotNull(value, "value");
+        service_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -174,7 +174,7 @@
 
     /// <summary>Field number for the "status" field.</summary>
     public const int StatusFieldNumber = 1;
-    private global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+    private global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus status_ = 0;
     public global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus Status {
       get { return status_; }
       set {
@@ -199,7 +199,7 @@
 
     public override int GetHashCode() {
       int hash = 1;
-      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) hash ^= Status.GetHashCode();
+      if (Status != 0) hash ^= Status.GetHashCode();
       return hash;
     }
 
@@ -208,7 +208,7 @@
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (Status != 0) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Status);
       }
@@ -216,7 +216,7 @@
 
     public int CalculateSize() {
       int size = 0;
-      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (Status != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
       }
       return size;
@@ -226,7 +226,7 @@
       if (other == null) {
         return;
       }
-      if (other.Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (other.Status != 0) {
         Status = other.Status;
       }
     }
@@ -251,9 +251,9 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       public enum ServingStatus {
-        UNKNOWN = 0,
-        SERVING = 1,
-        NOT_SERVING = 2,
+        [pbr::OriginalName("UNKNOWN")] Unknown = 0,
+        [pbr::OriginalName("SERVING")] Serving = 1,
+        [pbr::OriginalName("NOT_SERVING")] NotServing = 2,
       }
 
     }
diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config
index 358a978..a52d9e5 100644
--- a/src/csharp/Grpc.HealthCheck/packages.config
+++ b/src/csharp/Grpc.HealthCheck/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
index 9eaf6bf..39b9ae0 100644
--- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
@@ -32,6 +32,7 @@
 #endregion
 
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
@@ -41,7 +42,9 @@
 using System.Threading.Tasks;
 using Google.Protobuf;
 using Grpc.Core;
+using Grpc.Core.Internal;
 using Grpc.Core.Logging;
+using Grpc.Core.Profiling;
 using Grpc.Core.Utils;
 using NUnit.Framework;
 using Grpc.Testing;
@@ -55,6 +58,15 @@
     {
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<ClientRunners>();
 
+        // Profilers to use for clients.
+        static readonly BlockingCollection<BasicProfiler> profilers = new BlockingCollection<BasicProfiler>();
+
+        internal static void AddProfiler(BasicProfiler profiler)
+        {
+            GrpcPreconditions.CheckNotNull(profiler);
+            profilers.Add(profiler);
+        }
+
         /// <summary>
         /// Creates a started client runner.
         /// </summary>
@@ -83,7 +95,8 @@
                 config.OutstandingRpcsPerChannel,
                 config.LoadParams,
                 config.PayloadConfig,
-                config.HistogramParams);
+                config.HistogramParams,
+                () => GetNextProfiler());
         }
 
         private static List<Channel> CreateChannels(int clientChannels, IEnumerable<string> serverTargets, SecurityParams securityParams)
@@ -110,9 +123,16 @@
             }
             return result;
         }
+
+        private static BasicProfiler GetNextProfiler()
+        {
+            BasicProfiler result = null;
+            profilers.TryTake(out result);
+            return result;
+        }
     }
 
-    public class ClientRunnerImpl : IClientRunner
+    internal class ClientRunnerImpl : IClientRunner
     {
         const double SecondsToNanos = 1e9;
 
@@ -125,8 +145,9 @@
         readonly List<Task> runnerTasks;
         readonly CancellationTokenSource stoppedCts = new CancellationTokenSource();
         readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+        readonly AtomicCounter statsResetCount = new AtomicCounter();
         
-        public ClientRunnerImpl(List<Channel> channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams)
+        public ClientRunnerImpl(List<Channel> channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams, Func<BasicProfiler> profilerFactory)
         {
             GrpcPreconditions.CheckArgument(outstandingRpcsPerChannel > 0, "outstandingRpcsPerChannel");
             GrpcPreconditions.CheckNotNull(histogramParams, "histogramParams");
@@ -142,7 +163,8 @@
                 for (int i = 0; i < outstandingRpcsPerChannel; i++)
                 {
                     var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel);
-                    this.runnerTasks.Add(RunClientAsync(channel, timer));
+                    var optionalProfiler = profilerFactory();
+                    this.runnerTasks.Add(RunClientAsync(channel, timer, optionalProfiler));
                 }
             }
         }
@@ -152,6 +174,11 @@
             var histogramData = histogram.GetSnapshot(reset);
             var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
 
+            if (reset)
+            {
+                statsResetCount.Increment();
+            }
+
             // TODO: populate user time and system time
             return new ClientStats
             {
@@ -175,14 +202,28 @@
             }
         }
 
-        private void RunUnary(Channel channel, IInterarrivalTimer timer)
+        private void RunUnary(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler)
         {
+            if (optionalProfiler != null)
+            {
+                Profilers.SetForCurrentThread(optionalProfiler);
+            }
+
+            bool profilerReset = false;
+
             var client = BenchmarkService.NewClient(channel);
             var request = CreateSimpleRequest();
             var stopwatch = new Stopwatch();
 
             while (!stoppedCts.Token.IsCancellationRequested)
             {
+                // after the first stats reset, also reset the profiler.
+                if (optionalProfiler != null && !profilerReset && statsResetCount.Count > 0)
+                {
+                    optionalProfiler.Reset();
+                    profilerReset = true;
+                }
+
                 stopwatch.Restart();
                 client.UnaryCall(request);
                 stopwatch.Stop();
@@ -268,29 +309,29 @@
             }
         }
 
-        private Task RunClientAsync(Channel channel, IInterarrivalTimer timer)
+        private Task RunClientAsync(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler)
         {
             if (payloadConfig.PayloadCase == PayloadConfig.PayloadOneofCase.BytebufParams)
             {
-                GrpcPreconditions.CheckArgument(clientType == ClientType.ASYNC_CLIENT, "Generic client only supports async API");
-                GrpcPreconditions.CheckArgument(rpcType == RpcType.STREAMING, "Generic client only supports streaming calls");
+                GrpcPreconditions.CheckArgument(clientType == ClientType.AsyncClient, "Generic client only supports async API");
+                GrpcPreconditions.CheckArgument(rpcType == RpcType.Streaming, "Generic client only supports streaming calls");
                 return RunGenericStreamingAsync(channel, timer);
             }
 
             GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams);
-            if (clientType == ClientType.SYNC_CLIENT)
+            if (clientType == ClientType.SyncClient)
             {
-                GrpcPreconditions.CheckArgument(rpcType == RpcType.UNARY, "Sync client can only be used for Unary calls in C#");
+                GrpcPreconditions.CheckArgument(rpcType == RpcType.Unary, "Sync client can only be used for Unary calls in C#");
                 // create a dedicated thread for the synchronous client
-                return Task.Factory.StartNew(() => RunUnary(channel, timer), TaskCreationOptions.LongRunning);
+                return Task.Factory.StartNew(() => RunUnary(channel, timer, optionalProfiler), TaskCreationOptions.LongRunning);
             }
-            else if (clientType == ClientType.ASYNC_CLIENT)
+            else if (clientType == ClientType.AsyncClient)
             {
                 switch (rpcType)
                 {
-                    case RpcType.UNARY:
+                    case RpcType.Unary:
                         return RunUnaryAsync(channel, timer);
-                    case RpcType.STREAMING:
+                    case RpcType.Streaming:
                         return RunStreamingPingPongAsync(channel, timer);
                 }
             }
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 3fa8d43..412f800 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -85,25 +85,25 @@
             "RUFNSU5HEAFiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
-          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary" }, null, null, null)
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary" }, null, null, null)
           }));
     }
     #endregion
@@ -115,27 +115,27 @@
     ///  Many languages support a basic distinction between using
     ///  sync or async client, and this allows the specification
     /// </summary>
-    SYNC_CLIENT = 0,
-    ASYNC_CLIENT = 1,
+    [pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0,
+    [pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1,
     /// <summary>
     ///  used for some language-specific variants
     /// </summary>
-    OTHER_CLIENT = 2,
+    [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
   }
 
   public enum ServerType {
-    SYNC_SERVER = 0,
-    ASYNC_SERVER = 1,
-    ASYNC_GENERIC_SERVER = 2,
+    [pbr::OriginalName("SYNC_SERVER")] SyncServer = 0,
+    [pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1,
+    [pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2,
     /// <summary>
     ///  used for some language-specific variants
     /// </summary>
-    OTHER_SERVER = 3,
+    [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3,
   }
 
   public enum RpcType {
-    UNARY = 0,
-    STREAMING = 1,
+    [pbr::OriginalName("UNARY")] Unary = 0,
+    [pbr::OriginalName("STREAMING")] Streaming = 1,
   }
 
   #endregion
@@ -547,7 +547,7 @@
     public string ServerHostOverride {
       get { return serverHostOverride_; }
       set {
-        serverHostOverride_ = pb::Preconditions.CheckNotNull(value, "value");
+        serverHostOverride_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -686,7 +686,7 @@
 
     /// <summary>Field number for the "client_type" field.</summary>
     public const int ClientTypeFieldNumber = 2;
-    private global::Grpc.Testing.ClientType clientType_ = global::Grpc.Testing.ClientType.SYNC_CLIENT;
+    private global::Grpc.Testing.ClientType clientType_ = 0;
     public global::Grpc.Testing.ClientType ClientType {
       get { return clientType_; }
       set {
@@ -747,7 +747,7 @@
 
     /// <summary>Field number for the "rpc_type" field.</summary>
     public const int RpcTypeFieldNumber = 8;
-    private global::Grpc.Testing.RpcType rpcType_ = global::Grpc.Testing.RpcType.UNARY;
+    private global::Grpc.Testing.RpcType rpcType_ = 0;
     public global::Grpc.Testing.RpcType RpcType {
       get { return rpcType_; }
       set {
@@ -819,7 +819,7 @@
     public string OtherClientApi {
       get { return otherClientApi_; }
       set {
-        otherClientApi_ = pb::Preconditions.CheckNotNull(value, "value");
+        otherClientApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -853,12 +853,12 @@
     public override int GetHashCode() {
       int hash = 1;
       hash ^= serverTargets_.GetHashCode();
-      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) hash ^= ClientType.GetHashCode();
+      if (ClientType != 0) hash ^= ClientType.GetHashCode();
       if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
       if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode();
       if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode();
       if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode();
-      if (RpcType != global::Grpc.Testing.RpcType.UNARY) hash ^= RpcType.GetHashCode();
+      if (RpcType != 0) hash ^= RpcType.GetHashCode();
       if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
       if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
       if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
@@ -874,7 +874,7 @@
 
     public void WriteTo(pb::CodedOutputStream output) {
       serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
-      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+      if (ClientType != 0) {
         output.WriteRawTag(16);
         output.WriteEnum((int) ClientType);
       }
@@ -894,7 +894,7 @@
         output.WriteRawTag(56);
         output.WriteInt32(AsyncClientThreads);
       }
-      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+      if (RpcType != 0) {
         output.WriteRawTag(64);
         output.WriteEnum((int) RpcType);
       }
@@ -924,7 +924,7 @@
     public int CalculateSize() {
       int size = 0;
       size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
-      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+      if (ClientType != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType);
       }
       if (securityParams_ != null) {
@@ -939,7 +939,7 @@
       if (AsyncClientThreads != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads);
       }
-      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+      if (RpcType != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType);
       }
       if (loadParams_ != null) {
@@ -966,7 +966,7 @@
         return;
       }
       serverTargets_.Add(other.serverTargets_);
-      if (other.ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+      if (other.ClientType != 0) {
         ClientType = other.ClientType;
       }
       if (other.securityParams_ != null) {
@@ -984,7 +984,7 @@
       if (other.AsyncClientThreads != 0) {
         AsyncClientThreads = other.AsyncClientThreads;
       }
-      if (other.RpcType != global::Grpc.Testing.RpcType.UNARY) {
+      if (other.RpcType != 0) {
         RpcType = other.RpcType;
       }
       if (other.loadParams_ != null) {
@@ -1515,7 +1515,7 @@
 
     /// <summary>Field number for the "server_type" field.</summary>
     public const int ServerTypeFieldNumber = 1;
-    private global::Grpc.Testing.ServerType serverType_ = global::Grpc.Testing.ServerType.SYNC_SERVER;
+    private global::Grpc.Testing.ServerType serverType_ = 0;
     public global::Grpc.Testing.ServerType ServerType {
       get { return serverType_; }
       set {
@@ -1606,7 +1606,7 @@
     public string OtherServerApi {
       get { return otherServerApi_; }
       set {
-        otherServerApi_ = pb::Preconditions.CheckNotNull(value, "value");
+        otherServerApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -1634,7 +1634,7 @@
 
     public override int GetHashCode() {
       int hash = 1;
-      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) hash ^= ServerType.GetHashCode();
+      if (ServerType != 0) hash ^= ServerType.GetHashCode();
       if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
       if (Port != 0) hash ^= Port.GetHashCode();
       if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
@@ -1650,7 +1650,7 @@
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+      if (ServerType != 0) {
         output.WriteRawTag(8);
         output.WriteEnum((int) ServerType);
       }
@@ -1683,7 +1683,7 @@
 
     public int CalculateSize() {
       int size = 0;
-      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+      if (ServerType != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
       }
       if (securityParams_ != null) {
@@ -1712,7 +1712,7 @@
       if (other == null) {
         return;
       }
-      if (other.ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+      if (other.ServerType != 0) {
         ServerType = other.ServerType;
       }
       if (other.securityParams_ != null) {
@@ -2436,7 +2436,7 @@
     public string Name {
       get { return name_; }
       set {
-        name_ = pb::Preconditions.CheckNotNull(value, "value");
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs
index 4323c5a..cf1c23f 100644
--- a/src/csharp/Grpc.IntegrationTesting/Empty.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs
@@ -27,8 +27,8 @@
             "c3RpbmciBwoFRW1wdHliBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Empty), global::Grpc.Testing.Empty.Parser, null, null, null, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Empty), global::Grpc.Testing.Empty.Parser, null, null, null, null)
           }));
     }
     #endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 9685cf1..0089049 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -61,7 +61,7 @@
       <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
     </Reference>
     <Reference Include="Google.Protobuf">
-      <HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
+      <HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json">
       <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index cff8508..aea40af 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -230,13 +230,13 @@
             Console.WriteLine("running large_unary");
             var request = new SimpleRequest
             {
-                ResponseType = PayloadType.COMPRESSABLE,
+                ResponseType = PayloadType.Compressable,
                 ResponseSize = 314159,
                 Payload = CreateZerosPayload(271828)
             };
             var response = client.UnaryCall(request);
 
-            Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
+            Assert.AreEqual(PayloadType.Compressable, response.Payload.Type);
             Assert.AreEqual(314159, response.Payload.Body.Length);
             Console.WriteLine("Passed!");
         }
@@ -265,7 +265,7 @@
 
             var request = new StreamingOutputCallRequest
             {
-                ResponseType = PayloadType.COMPRESSABLE,
+                ResponseType = PayloadType.Compressable,
                 ResponseParameters = { bodySizes.ConvertAll((size) => new ResponseParameters { Size = size }) }
             };
 
@@ -274,7 +274,7 @@
                 var responseList = await call.ResponseStream.ToListAsync();
                 foreach (var res in responseList)
                 {
-                    Assert.AreEqual(PayloadType.COMPRESSABLE, res.Payload.Type);
+                    Assert.AreEqual(PayloadType.Compressable, res.Payload.Type);
                 }
                 CollectionAssert.AreEqual(bodySizes, responseList.ConvertAll((item) => item.Payload.Body.Length));
             }
@@ -289,46 +289,46 @@
             {
                 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 31415 } },
                     Payload = CreateZerosPayload(27182)
                 });
 
                 Assert.IsTrue(await call.ResponseStream.MoveNext());
-                Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
+                Assert.AreEqual(PayloadType.Compressable, call.ResponseStream.Current.Payload.Type);
                 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
 
                 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 9 } },
                     Payload = CreateZerosPayload(8)
                 });
 
                 Assert.IsTrue(await call.ResponseStream.MoveNext());
-                Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
+                Assert.AreEqual(PayloadType.Compressable, call.ResponseStream.Current.Payload.Type);
                 Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length);
 
                 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 2653 } },
                     Payload = CreateZerosPayload(1828)
                 });
 
                 Assert.IsTrue(await call.ResponseStream.MoveNext());
-                Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
+                Assert.AreEqual(PayloadType.Compressable, call.ResponseStream.Current.Payload.Type);
                 Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length);
 
                 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 58979 } },
                     Payload = CreateZerosPayload(45904)
                 });
 
                 Assert.IsTrue(await call.ResponseStream.MoveNext());
-                Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
+                Assert.AreEqual(PayloadType.Compressable, call.ResponseStream.Current.Payload.Type);
                 Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length);
 
                 await call.RequestStream.CompleteAsync();
@@ -357,7 +357,7 @@
 
             var request = new SimpleRequest
             {
-                ResponseType = PayloadType.COMPRESSABLE,
+                ResponseType = PayloadType.Compressable,
                 ResponseSize = 314159,
                 Payload = CreateZerosPayload(271828),
                 FillUsername = true,
@@ -367,7 +367,7 @@
             // not setting credentials here because they were set on channel already
             var response = client.UnaryCall(request);
 
-            Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
+            Assert.AreEqual(PayloadType.Compressable, response.Payload.Type);
             Assert.AreEqual(314159, response.Payload.Body.Length);
             Assert.False(string.IsNullOrEmpty(response.OauthScope));
             Assert.True(oauthScope.Contains(response.OauthScope));
@@ -381,7 +381,7 @@
            
             var request = new SimpleRequest
             {
-                ResponseType = PayloadType.COMPRESSABLE,
+                ResponseType = PayloadType.Compressable,
                 ResponseSize = 314159,
                 Payload = CreateZerosPayload(271828),
                 FillUsername = true,
@@ -390,7 +390,7 @@
             // not setting credentials here because they were set on channel already
             var response = client.UnaryCall(request);
 
-            Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
+            Assert.AreEqual(PayloadType.Compressable, response.Payload.Type);
             Assert.AreEqual(314159, response.Payload.Body.Length);
             Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
             Console.WriteLine("Passed!");
@@ -460,19 +460,27 @@
             {
                 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 31415 } },
                     Payload = CreateZerosPayload(27182)
                 });
 
                 Assert.IsTrue(await call.ResponseStream.MoveNext());
-                Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
+                Assert.AreEqual(PayloadType.Compressable, call.ResponseStream.Current.Payload.Type);
                 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
 
                 cts.Cancel();
 
-                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
-                Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
+                try
+                {
+                    // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
+                    await call.ResponseStream.MoveNext();
+                    Assert.Fail();
+                }
+                catch (RpcException ex)
+                {
+                    Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
+                }
             }
             Console.WriteLine("Passed!");
         }
@@ -497,9 +505,16 @@
                     // Deadline was reached before write has started. Eat the exception and continue.
                 }
 
-                var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
-                // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
-                Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
+                try
+                {
+                    await call.ResponseStream.MoveNext();
+                    Assert.Fail();
+                }
+                catch (RpcException ex)
+                {
+                    // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
+                    Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
+                }
             }
             Console.WriteLine("Passed!");
         }
@@ -511,7 +526,7 @@
                 // step 1: test unary call
                 var request = new SimpleRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseSize = 314159,
                     Payload = CreateZerosPayload(271828)
                 };
@@ -530,7 +545,7 @@
                 // step 2: test full duplex call
                 var request = new StreamingOutputCallRequest
                 {
-                    ResponseType = PayloadType.COMPRESSABLE,
+                    ResponseType = PayloadType.Compressable,
                     ResponseParameters = { new ResponseParameters { Size = 31415 } },
                     Payload = CreateZerosPayload(27182)
                 };
@@ -577,9 +592,17 @@
                 await call.RequestStream.WriteAsync(request);
                 await call.RequestStream.CompleteAsync();
 
-                var e = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.ToListAsync());
-                Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
-                Assert.AreEqual(echoStatus.Message, e.Status.Detail);
+                try
+                {
+                    // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
+                    await call.ResponseStream.ToListAsync();
+                    Assert.Fail();
+                }
+                catch (RpcException e)
+                {
+                    Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
+                    Assert.AreEqual(echoStatus.Message, e.Status.Detail);
+                }
             }
 
             Console.WriteLine("Passed!");
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index fcff475..d42501a 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -55,18 +55,18 @@
             "TkUQABIICgRHWklQEAESCwoHREVGTEFURRACYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), typeof(global::Grpc.Testing.CompressionType), }, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompression", "ResponseStatus" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseCompression", "ResponseStatus" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ReconnectParams), global::Grpc.Testing.ReconnectParams.Parser, new[]{ "MaxReconnectBackoffMs" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ReconnectInfo), global::Grpc.Testing.ReconnectInfo.Parser, new[]{ "Passed", "BackoffMs" }, null, null, null)
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), typeof(global::Grpc.Testing.CompressionType), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompression", "ResponseStatus" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseCompression", "ResponseStatus" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectParams), global::Grpc.Testing.ReconnectParams.Parser, new[]{ "MaxReconnectBackoffMs" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectInfo), global::Grpc.Testing.ReconnectInfo.Parser, new[]{ "Passed", "BackoffMs" }, null, null, null)
           }));
     }
     #endregion
@@ -80,15 +80,15 @@
     /// <summary>
     ///  Compressable text format.
     /// </summary>
-    COMPRESSABLE = 0,
+    [pbr::OriginalName("COMPRESSABLE")] Compressable = 0,
     /// <summary>
     ///  Uncompressable binary format.
     /// </summary>
-    UNCOMPRESSABLE = 1,
+    [pbr::OriginalName("UNCOMPRESSABLE")] Uncompressable = 1,
     /// <summary>
     ///  Randomly chosen from all other formats defined in this enum.
     /// </summary>
-    RANDOM = 2,
+    [pbr::OriginalName("RANDOM")] Random = 2,
   }
 
   /// <summary>
@@ -98,9 +98,9 @@
     /// <summary>
     ///  No compression
     /// </summary>
-    NONE = 0,
-    GZIP = 1,
-    DEFLATE = 2,
+    [pbr::OriginalName("NONE")] None = 0,
+    [pbr::OriginalName("GZIP")] Gzip = 1,
+    [pbr::OriginalName("DEFLATE")] Deflate = 2,
   }
 
   #endregion
@@ -139,7 +139,7 @@
 
     /// <summary>Field number for the "type" field.</summary>
     public const int TypeFieldNumber = 1;
-    private global::Grpc.Testing.PayloadType type_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    private global::Grpc.Testing.PayloadType type_ = 0;
     /// <summary>
     ///  The type of data in body.
     /// </summary>
@@ -159,7 +159,7 @@
     public pb::ByteString Body {
       get { return body_; }
       set {
-        body_ = pb::Preconditions.CheckNotNull(value, "value");
+        body_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -181,7 +181,7 @@
 
     public override int GetHashCode() {
       int hash = 1;
-      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= Type.GetHashCode();
+      if (Type != 0) hash ^= Type.GetHashCode();
       if (Body.Length != 0) hash ^= Body.GetHashCode();
       return hash;
     }
@@ -191,7 +191,7 @@
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (Type != 0) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Type);
       }
@@ -203,7 +203,7 @@
 
     public int CalculateSize() {
       int size = 0;
-      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (Type != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
       }
       if (Body.Length != 0) {
@@ -216,7 +216,7 @@
       if (other == null) {
         return;
       }
-      if (other.Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (other.Type != 0) {
         Type = other.Type;
       }
       if (other.Body.Length != 0) {
@@ -293,7 +293,7 @@
     public string Message {
       get { return message_; }
       set {
-        message_ = pb::Preconditions.CheckNotNull(value, "value");
+        message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -417,7 +417,7 @@
 
     /// <summary>Field number for the "response_type" field.</summary>
     public const int ResponseTypeFieldNumber = 1;
-    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    private global::Grpc.Testing.PayloadType responseType_ = 0;
     /// <summary>
     ///  Desired payload type in the response from the server.
     ///  If response_type is RANDOM, server randomly chooses one from other formats.
@@ -484,7 +484,7 @@
 
     /// <summary>Field number for the "response_compression" field.</summary>
     public const int ResponseCompressionFieldNumber = 6;
-    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
+    private global::Grpc.Testing.CompressionType responseCompression_ = 0;
     /// <summary>
     ///  Compression algorithm to be used by the server for the response (stream)
     /// </summary>
@@ -531,12 +531,12 @@
 
     public override int GetHashCode() {
       int hash = 1;
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode();
+      if (ResponseType != 0) hash ^= ResponseType.GetHashCode();
       if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode();
       if (payload_ != null) hash ^= Payload.GetHashCode();
       if (FillUsername != false) hash ^= FillUsername.GetHashCode();
       if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode();
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) hash ^= ResponseCompression.GetHashCode();
+      if (ResponseCompression != 0) hash ^= ResponseCompression.GetHashCode();
       if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
       return hash;
     }
@@ -546,7 +546,7 @@
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (ResponseType != 0) {
         output.WriteRawTag(8);
         output.WriteEnum((int) ResponseType);
       }
@@ -566,7 +566,7 @@
         output.WriteRawTag(40);
         output.WriteBool(FillOauthScope);
       }
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (ResponseCompression != 0) {
         output.WriteRawTag(48);
         output.WriteEnum((int) ResponseCompression);
       }
@@ -578,7 +578,7 @@
 
     public int CalculateSize() {
       int size = 0;
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (ResponseType != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
       }
       if (ResponseSize != 0) {
@@ -593,7 +593,7 @@
       if (FillOauthScope != false) {
         size += 1 + 1;
       }
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (ResponseCompression != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseCompression);
       }
       if (responseStatus_ != null) {
@@ -606,7 +606,7 @@
       if (other == null) {
         return;
       }
-      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (other.ResponseType != 0) {
         ResponseType = other.ResponseType;
       }
       if (other.ResponseSize != 0) {
@@ -624,7 +624,7 @@
       if (other.FillOauthScope != false) {
         FillOauthScope = other.FillOauthScope;
       }
-      if (other.ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (other.ResponseCompression != 0) {
         ResponseCompression = other.ResponseCompression;
       }
       if (other.responseStatus_ != null) {
@@ -737,7 +737,7 @@
     public string Username {
       get { return username_; }
       set {
-        username_ = pb::Preconditions.CheckNotNull(value, "value");
+        username_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -750,7 +750,7 @@
     public string OauthScope {
       get { return oauthScope_; }
       set {
-        oauthScope_ = pb::Preconditions.CheckNotNull(value, "value");
+        oauthScope_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -1259,7 +1259,7 @@
 
     /// <summary>Field number for the "response_type" field.</summary>
     public const int ResponseTypeFieldNumber = 1;
-    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
+    private global::Grpc.Testing.PayloadType responseType_ = 0;
     /// <summary>
     ///  Desired payload type in the response from the server.
     ///  If response_type is RANDOM, the payload from each response in the stream
@@ -1300,7 +1300,7 @@
 
     /// <summary>Field number for the "response_compression" field.</summary>
     public const int ResponseCompressionFieldNumber = 6;
-    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
+    private global::Grpc.Testing.CompressionType responseCompression_ = 0;
     /// <summary>
     ///  Compression algorithm to be used by the server for the response (stream)
     /// </summary>
@@ -1345,10 +1345,10 @@
 
     public override int GetHashCode() {
       int hash = 1;
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode();
+      if (ResponseType != 0) hash ^= ResponseType.GetHashCode();
       hash ^= responseParameters_.GetHashCode();
       if (payload_ != null) hash ^= Payload.GetHashCode();
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) hash ^= ResponseCompression.GetHashCode();
+      if (ResponseCompression != 0) hash ^= ResponseCompression.GetHashCode();
       if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
       return hash;
     }
@@ -1358,7 +1358,7 @@
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (ResponseType != 0) {
         output.WriteRawTag(8);
         output.WriteEnum((int) ResponseType);
       }
@@ -1367,7 +1367,7 @@
         output.WriteRawTag(26);
         output.WriteMessage(Payload);
       }
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (ResponseCompression != 0) {
         output.WriteRawTag(48);
         output.WriteEnum((int) ResponseCompression);
       }
@@ -1379,14 +1379,14 @@
 
     public int CalculateSize() {
       int size = 0;
-      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (ResponseType != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
       }
       size += responseParameters_.CalculateSize(_repeated_responseParameters_codec);
       if (payload_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
       }
-      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (ResponseCompression != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseCompression);
       }
       if (responseStatus_ != null) {
@@ -1399,7 +1399,7 @@
       if (other == null) {
         return;
       }
-      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
+      if (other.ResponseType != 0) {
         ResponseType = other.ResponseType;
       }
       responseParameters_.Add(other.responseParameters_);
@@ -1409,7 +1409,7 @@
         }
         Payload.MergeFrom(other.Payload);
       }
-      if (other.ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
+      if (other.ResponseCompression != 0) {
         ResponseCompression = other.ResponseCompression;
       }
       if (other.responseStatus_ != null) {
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
index 3163949..8f31fbc 100644
--- a/src/csharp/Grpc.IntegrationTesting/Metrics.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -34,10 +34,10 @@
             "dWdlUmVzcG9uc2ViBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null)
           }));
     }
     #endregion
@@ -92,7 +92,7 @@
     public string Name {
       get { return name_; }
       set {
-        name_ = pb::Preconditions.CheckNotNull(value, "value");
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
@@ -121,7 +121,7 @@
     public string StringValue {
       get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; }
       set {
-        value_ = pb::Preconditions.CheckNotNull(value, "value");
+        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
         valueCase_ = ValueOneofCase.StringValue;
       }
     }
@@ -299,7 +299,7 @@
     public string Name {
       get { return name_; }
       set {
-        name_ = pb::Preconditions.CheckNotNull(value, "value");
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
 
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
index 663f625..3ad7a44 100644
--- a/src/csharp/Grpc.IntegrationTesting/Payloads.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -34,11 +34,11 @@
             "aW5nLkNvbXBsZXhQcm90b1BhcmFtc0gAQgkKB3BheWxvYWRiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ByteBufferParams), global::Grpc.Testing.ByteBufferParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), global::Grpc.Testing.SimpleProtoParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), global::Grpc.Testing.ComplexProtoParams.Parser, null, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PayloadConfig), global::Grpc.Testing.PayloadConfig.Parser, new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ByteBufferParams), global::Grpc.Testing.ByteBufferParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), global::Grpc.Testing.SimpleProtoParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), global::Grpc.Testing.ComplexProtoParams.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PayloadConfig), global::Grpc.Testing.PayloadConfig.Parser, new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null)
           }));
     }
     #endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
index 13ab5a2..b2f2e4d 100644
--- a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -55,7 +55,7 @@
         {
             var serverConfig = new ServerConfig
             {
-                ServerType = ServerType.ASYNC_SERVER
+                ServerType = ServerType.AsyncServer
             };
             serverRunner = ServerRunners.CreateStarted(serverConfig);
         }
@@ -75,7 +75,7 @@
             var config = new ClientConfig
             {
                 ServerTargets = { string.Format("{0}:{1}", "localhost", serverRunner.BoundPort) },
-                RpcType = RpcType.UNARY,
+                RpcType = RpcType.Unary,
                 LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() },
                 PayloadConfig = new PayloadConfig
                 {
diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
index d785944..8689d18 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -77,13 +77,13 @@
             }
 
             ServerServiceDefinition service = null;
-            if (config.ServerType == ServerType.ASYNC_SERVER)
+            if (config.ServerType == ServerType.AsyncServer)
             {
                 GrpcPreconditions.CheckArgument(config.PayloadConfig == null,
                     "ServerConfig.PayloadConfig shouldn't be set for BenchmarkService based server.");    
                 service = BenchmarkService.BindService(new BenchmarkServiceImpl());
             }
-            else if (config.ServerType == ServerType.ASYNC_GENERIC_SERVER)
+            else if (config.ServerType == ServerType.AsyncGenericServer)
             {
                 var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize);
                 service = GenericService.BindHandler(genericService.StreamingCall);
diff --git a/src/csharp/Grpc.IntegrationTesting/Services.cs b/src/csharp/Grpc.IntegrationTesting/Services.cs
index a8475c1..e10b45c 100644
--- a/src/csharp/Grpc.IntegrationTesting/Services.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Services.cs
@@ -39,7 +39,7 @@
             "YgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, },
-          new pbr::GeneratedCodeInfo(null, null));
+          new pbr::GeneratedClrTypeInfo(null, null));
     }
     #endregion
 
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
index 39c00ea..304d676 100644
--- a/src/csharp/Grpc.IntegrationTesting/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -35,11 +35,11 @@
             "ZXIYAyABKAESEwoLdGltZV9zeXN0ZW0YBCABKAFiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
-          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null)
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null)
           }));
     }
     #endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs
index 363f644..9258dc1 100644
--- a/src/csharp/Grpc.IntegrationTesting/Test.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Test.cs
@@ -46,7 +46,7 @@
             "cnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mb2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.EmptyReflection.Descriptor, global::Grpc.Testing.MessagesReflection.Descriptor, },
-          new pbr::GeneratedCodeInfo(null, null));
+          new pbr::GeneratedClrTypeInfo(null, null));
     }
     #endregion
 
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
index 80dad9f..c9eca73 100644
--- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
@@ -64,7 +64,7 @@
             {
                 Stats = runner.GetStats(false),
                 Port = runner.BoundPort,
-                Cores = 0,  // TODO: set number of cores
+                Cores = Environment.ProcessorCount,
             });
                 
             while (await requestStream.MoveNext())
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 3fef67d..3161c5b 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -4,7 +4,7 @@
   <package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
   <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
   <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
-  <package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
   <package id="Ix-Async" version="1.2.5" targetFramework="net45" />
   <package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index 28e4262..1cc63da 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -31,7 +31,7 @@
 
 @rem Current package versions
 set VERSION=0.15.0-dev
-set PROTOBUF_VERSION=3.0.0-beta2
+set PROTOBUF_VERSION=3.0.0-beta3
 
 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
 set VERSION_WITH_BETA=%VERSION%-beta
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 5b8ff9b..4beef9d 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -806,11 +806,14 @@
 /* Server */
 
 GPR_EXPORT grpc_server *GPR_CALLTYPE
-grpcsharp_server_create(grpc_completion_queue *cq,
-                        const grpc_channel_args *args) {
-  grpc_server *server = grpc_server_create(args, NULL);
+grpcsharp_server_create(const grpc_channel_args *args) {
+  return grpc_server_create(args, NULL);
+}
+
+GPR_EXPORT void GPR_CALLTYPE
+grpcsharp_server_register_completion_queue(grpc_server *server,
+                                           grpc_completion_queue *cq) {
   grpc_server_register_completion_queue(server, cq, NULL);
-  return server;
 }
 
 GPR_EXPORT int32_t GPR_CALLTYPE
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index b9e1fe9..dd1b777 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -35,15 +35,15 @@
 
 #include "server.h"
 
-#include <node.h>
 #include <nan.h>
+#include <node.h>
 
 #include <vector>
+#include "call.h"
+#include "completion_queue_async_worker.h"
 #include "grpc/grpc.h"
 #include "grpc/grpc_security.h"
 #include "grpc/support/log.h"
-#include "call.h"
-#include "completion_queue_async_worker.h"
 #include "server_credentials.h"
 #include "timeval.h"
 
@@ -100,8 +100,8 @@
     Nan::Set(obj, Nan::New("host").ToLocalChecked(),
              Nan::New(details.host).ToLocalChecked());
     Nan::Set(obj, Nan::New("deadline").ToLocalChecked(),
-             Nan::New<Date>(
-                 TimespecToMilliseconds(details.deadline)).ToLocalChecked());
+             Nan::New<Date>(TimespecToMilliseconds(details.deadline))
+                 .ToLocalChecked());
     Nan::Set(obj, Nan::New("metadata").ToLocalChecked(),
              ParseMetadata(&request_metadata));
     return scope.Escape(obj);
@@ -117,14 +117,13 @@
   grpc_metadata_array request_metadata;
 
  protected:
-  std::string GetTypeString() const {
-    return "new_call";
-  }
+  std::string GetTypeString() const { return "new_call"; }
 };
 
 Server::Server(grpc_server *server) : wrapped_server(server) {
   shutdown_queue = grpc_completion_queue_create(NULL);
-  grpc_server_register_completion_queue(server, shutdown_queue, NULL);
+  grpc_server_register_non_listening_completion_queue(server, shutdown_queue,
+                                                      NULL);
 }
 
 Server::~Server() {
@@ -156,8 +155,7 @@
 }
 
 void Server::ShutdownServer() {
-  grpc_server_shutdown_and_notify(this->wrapped_server,
-                                  this->shutdown_queue,
+  grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue,
                                   NULL);
   grpc_server_cancel_all_calls(this->wrapped_server);
   grpc_completion_queue_pluck(this->shutdown_queue, NULL,
@@ -170,8 +168,8 @@
   if (!info.IsConstructCall()) {
     const int argc = 1;
     Local<Value> argv[argc] = {info[0]};
-    MaybeLocal<Object> maybe_instance = constructor->GetFunction()->NewInstance(
-        argc, argv);
+    MaybeLocal<Object> maybe_instance =
+        constructor->GetFunction()->NewInstance(argc, argv);
     if (maybe_instance.IsEmpty()) {
       // There's probably a pending exception
       return;
@@ -185,8 +183,9 @@
   grpc_channel_args *channel_args;
   if (!ParseChannelArgs(info[0], &channel_args)) {
     DeallocateChannelArgs(channel_args);
-    return Nan::ThrowTypeError("Server options must be an object with "
-                               "string keys and integer or string values");
+    return Nan::ThrowTypeError(
+        "Server options must be an object with "
+        "string keys and integer or string values");
   }
   wrapped_server = grpc_server_create(channel_args, NULL);
   DeallocateChannelArgs(channel_args);
@@ -218,8 +217,7 @@
 
 NAN_METHOD(Server::AddHttp2Port) {
   if (!HasInstance(info.This())) {
-    return Nan::ThrowTypeError(
-        "addHttp2Port can only be called on a Server");
+    return Nan::ThrowTypeError("addHttp2Port can only be called on a Server");
   }
   if (!info[0]->IsString()) {
     return Nan::ThrowTypeError(
@@ -239,8 +237,7 @@
                                                *Utf8String(info[0]));
   } else {
     port = grpc_server_add_secure_http2_port(server->wrapped_server,
-                                             *Utf8String(info[0]),
-                                             creds);
+                                             *Utf8String(info[0]), creds);
   }
   info.GetReturnValue().Set(Nan::New<Number>(port));
 }
@@ -262,8 +259,7 @@
   Server *server = ObjectWrap::Unwrap<Server>(info.This());
   unique_ptr<OpVec> ops(new OpVec());
   grpc_server_shutdown_and_notify(
-      server->wrapped_server,
-      CompletionQueueAsyncWorker::GetQueue(),
+      server->wrapped_server, CompletionQueueAsyncWorker::GetQueue(),
       new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
                      shared_ptr<Resources>(nullptr)));
   CompletionQueueAsyncWorker::Next();
diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec
new file mode 100644
index 0000000..20af764
--- /dev/null
+++ b/src/objective-c/CronetFramework.podspec
@@ -0,0 +1,43 @@
+# 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.
+
+
+Pod::Spec.new do |s|
+  s.name         = "CronetFramework"
+  s.version      = "0.0.2"
+  s.summary      = "Cronet, precompiled and used as a framework."
+  s.homepage     = "http://chromium.org"
+  s.license      = { :type => 'BSD' }
+  s.vendored_framework = "Cronet.framework"
+  s.author             = "The Chromium Authors"
+  s.ios.deployment_target = "8.0"
+  s.source       = { :http => 'https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework.zip' }
+  s.preserve_paths = "Cronet.framework"
+  s.public_header_files = "Cronet.framework/Headers/**/*{.h}"
+end
diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.h b/src/objective-c/GRPCClient/GRPCCall+Cronet.h
new file mode 100644
index 0000000..7f7fc6c
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ *
+ */
+#import <Cronet/Cronet.h>
+
+#import "GRPCCall.h"
+
+/**
+ * Methods for using cronet transport.
+ */
+@interface GRPCCall (Cronet)
+
+/**
+ * This method should be called before issuing the first RPC. It should be
+ * called only once. Create an instance of Cronet engine in your app elsewhere
+ * and pass the instance pointer in the cronet_engine parameter. Once set,
+ * all subsequent RPCs will use Cronet transport. The method is not thread
+ * safe.
+ */
++(void)useCronetWithEngine:(cronet_engine *)engine;
+
++(cronet_engine *)cronetEngine;
+
++(BOOL)isUsingCronet;
+
+@end
diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.m b/src/objective-c/GRPCClient/GRPCCall+Cronet.m
new file mode 100644
index 0000000..69a410e
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.m
@@ -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.
+ *
+ */
+
+#import "GRPCCall+Cronet.h"
+
+static BOOL useCronet = NO;
+static cronet_engine *globalCronetEngine;
+
+@implementation GRPCCall (Cronet)
+
++ (void)useCronetWithEngine:(cronet_engine *)engine {
+  useCronet = YES;
+  globalCronetEngine = engine;
+}
+
++ (cronet_engine *)cronetEngine {
+  return globalCronetEngine;
+}
+
++ (BOOL)isUsingCronet {
+  return useCronet;
+}
+
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h
index 70d1a9b..3219835 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.h
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.h
@@ -56,6 +56,12 @@
 + (nullable GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host;
 
 /**
+ * Creates a secure channel to the specified @c host using Cronet as a transport mechanism.
+ */
++ (nullable GRPCChannel *)secureCronetChannelWithHost:(NSString *)host
+                                          channelArgs:(NSDictionary *)channelArgs;
+
+/**
  * Creates a secure channel to the specified @c host using the specified @c credentials and
  * @c channelArgs. Only in tests should @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set.
  */
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index 203ef58..e4e0dbe 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -34,10 +34,13 @@
 #import "GRPCChannel.h"
 
 #include <grpc/grpc_security.h>
+#include <grpc/grpc_cronet.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#import <Cronet/Cronet.h>
+#import <GRPCClient/GRPCCall+Cronet.h>
 #import "GRPCCompletionQueue.h"
 
 void freeChannelArgs(grpc_channel_args *channel_args) {
@@ -99,6 +102,22 @@
   grpc_channel_args *_channelArgs;
 }
 
+- (instancetype)initWithHost:(NSString *)host
+                cronetEngine:(cronet_engine *)cronetEngine
+                 channelArgs:(NSDictionary *)channelArgs {
+  if (!host) {
+    [NSException raise:NSInvalidArgumentException format:@"host argument missing"];
+  }
+
+  if (self = [super init]) {
+    _channelArgs = buildChannelArgs(channelArgs);
+    _host = [host copy];
+    _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs,
+                                                     NULL);
+  }
+
+  return self;
+}
 
 - (instancetype)initWithHost:(NSString *)host
                       secure:(BOOL)secure
@@ -133,6 +152,17 @@
   freeChannelArgs(_channelArgs);
 }
 
++ (GRPCChannel *)secureCronetChannelWithHost:(NSString *)host
+                                 channelArgs:(NSDictionary *)channelArgs {
+  cronet_engine *engine = [GRPCCall cronetEngine];
+  if (!engine) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"cronet_engine is NULL. Set it first."];
+    return nil;
+  }
+  return [[GRPCChannel alloc] initWithHost:host cronetEngine:engine channelArgs:channelArgs];
+}
+
 + (GRPCChannel *)secureChannelWithHost:(NSString *)host {
   return [[GRPCChannel alloc] initWithHost:host secure:YES credentials:NULL channelArgs:NULL];
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 43166cb..7da5088 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -37,6 +37,7 @@
 #include <grpc/grpc_security.h>
 #import <GRPCClient/GRPCCall.h>
 #import <GRPCClient/GRPCCall+ChannelArg.h>
+#import <GRPCClient/GRPCCall+Cronet.h>
 
 #import "GRPCChannel.h"
 #import "GRPCCompletionQueue.h"
@@ -200,15 +201,21 @@
 
 - (GRPCChannel *)newChannel {
   NSDictionary *args = [self channelArgs];
+  BOOL useCronet = [GRPCCall isUsingCronet];
   if (_secure) {
       GRPCChannel *channel;
       @synchronized(self) {
         if (_channelCreds == nil) {
           [self setTLSPEMRootCerts:nil withPrivateKey:nil withCertChain:nil error:nil];
         }
-        channel = [GRPCChannel secureChannelWithHost:_address
-                                          credentials:_channelCreds
-                                          channelArgs:args];
+        if (useCronet) {
+          channel = [GRPCChannel secureCronetChannelWithHost:_address
+                                                 channelArgs:args];
+        } else {
+          channel = [GRPCChannel secureChannelWithHost:_address
+                                            credentials:_channelCreds
+                                            channelArgs:args];
+        }
       }
       return channel;
   } else {
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index 4f096b9..781c500 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -35,7 +35,9 @@
 
 #include <grpc/status.h>
 
+#import <Cronet/Cronet.h>
 #import <GRPCClient/GRPCCall+Tests.h>
+#import <GRPCClient/GRPCCall+Cronet.h>
 #import <ProtoRPC/ProtoRPC.h>
 #import <RemoteTest/Empty.pbobjc.h>
 #import <RemoteTest/Messages.pbobjc.h>
@@ -78,6 +80,8 @@
 
 #pragma mark Tests
 
+static cronet_engine *cronetEngine = NULL;
+
 @implementation InteropTests {
   RMTTestService *_service;
 }
@@ -88,6 +92,15 @@
 
 - (void)setUp {
   _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
+#ifdef GRPC_COMPILE_WITH_CRONET
+  if (cronetEngine == NULL) {
+    // Cronet setup
+    [Cronet setHttp2Enabled:YES];
+    [Cronet start];
+    cronetEngine = [Cronet getGlobalEngine];
+    [GRPCCall useCronetWithEngine:cronetEngine];
+  }
+#endif
 }
 
 - (void)testEmptyUnaryRPC {
@@ -245,6 +258,8 @@
   [self waitForExpectationsWithTimeout:4 handler:nil];
 }
 
+#ifndef GRPC_COMPILE_WITH_CRONET
+// TODO(makdharma@): Fix this test
 - (void)testEmptyStreamRPC {
   XCTAssertNotNil(self.class.host);
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
@@ -258,6 +273,7 @@
   }];
   [self waitForExpectationsWithTimeout:2 handler:nil];
 }
+#endif
 
 - (void)testCancelAfterBeginRPC {
   XCTAssertNotNil(self.class.host);
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 7ec7a25..508641d 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -3,6 +3,7 @@
 
 pod 'Protobuf', :path => "../../../third_party/protobuf"
 pod 'BoringSSL', :podspec => ".."
+pod 'CronetFramework', :podspec => ".."
 pod 'gRPC', :path => "../../.."
 pod 'RemoteTest', :path => "RemoteTestClient"
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 66e6e6b..d42c580 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -336,6 +336,8 @@
   void grpc_server_register_completion_queue(grpc_server *server,
                                              grpc_completion_queue *cq,
                                              void *reserved) nogil
+  void grpc_server_register_non_listening_completion_queue(
+      grpc_server *server, grpc_completion_queue *cq, void *reserved) nogil
   int grpc_server_add_insecure_http2_port(
       grpc_server *server, const char *addr) nogil
   void grpc_server_start(grpc_server *server) nogil
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index 8419a59..5594875 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -81,11 +81,20 @@
           self.c_server, queue.c_completion_queue, NULL)
     self.registered_completion_queues.append(queue)
 
+  def register_non_listening_completion_queue(
+      self, CompletionQueue queue not None):
+    if self.is_started:
+      raise ValueError("cannot register completion queues after start")
+    with nogil:
+      grpc_server_register_non_listening_completion_queue(
+          self.c_server, queue.c_completion_queue, NULL)
+    self.registered_completion_queues.append(queue)
+
   def start(self):
     if self.is_started:
       raise ValueError("the server has already started")
     self.backup_shutdown_queue = CompletionQueue()
-    self.register_completion_queue(self.backup_shutdown_queue)
+    self.register_non_listening_completion_queue(self.backup_shutdown_queue)
     self.is_started = True
     with nogil:
       grpc_server_start(self.c_server)
@@ -169,4 +178,3 @@
           time.sleep(0)
       with nogil:
         grpc_server_destroy(self.c_server)
-
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 0955147..f71cf12 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -115,6 +115,7 @@
 grpc_server_request_registered_call_type grpc_server_request_registered_call_import;
 grpc_server_create_type grpc_server_create_import;
 grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
+grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import;
 grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import;
 grpc_server_start_type grpc_server_start_import;
 grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import;
@@ -386,6 +387,7 @@
   grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call");
   grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create");
   grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue");
+  grpc_server_register_non_listening_completion_queue_import = (grpc_server_register_non_listening_completion_queue_type) GetProcAddress(library, "grpc_server_register_non_listening_completion_queue");
   grpc_server_add_insecure_http2_port_import = (grpc_server_add_insecure_http2_port_type) GetProcAddress(library, "grpc_server_add_insecure_http2_port");
   grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start");
   grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index 6de2954..a364075 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -296,6 +296,9 @@
 typedef void(*grpc_server_register_completion_queue_type)(grpc_server *server, grpc_completion_queue *cq, void *reserved);
 extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
 #define grpc_server_register_completion_queue grpc_server_register_completion_queue_import
+typedef void(*grpc_server_register_non_listening_completion_queue_type)(grpc_server *server, grpc_completion_queue *q, void *reserved);
+extern grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import;
+#define grpc_server_register_non_listening_completion_queue grpc_server_register_non_listening_completion_queue_import
 typedef int(*grpc_server_add_insecure_http2_port_type)(grpc_server *server, const char *addr);
 extern grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import;
 #define grpc_server_add_insecure_http2_port grpc_server_add_insecure_http2_port_import
diff --git a/src/python/grpcio/grpc/framework/foundation/future.py b/src/python/grpcio/grpc/framework/foundation/future.py
index 9210616..6fb58ea 100644
--- a/src/python/grpcio/grpc/framework/foundation/future.py
+++ b/src/python/grpcio/grpc/framework/foundation/future.py
@@ -232,6 +232,6 @@
     immediately.
 
     Args:
-      fn: A callable taking a this Future object as its single parameter.
+      fn: A callable taking this Future object as its single parameter.
     """
     raise NotImplementedError()
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index cb18e5a..1427396 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -94,7 +94,6 @@
   'src/core/lib/iomgr/endpoint.c',
   'src/core/lib/iomgr/endpoint_pair_posix.c',
   'src/core/lib/iomgr/endpoint_pair_windows.c',
-  'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
   'src/core/lib/iomgr/ev_poll_posix.c',
   'src/core/lib/iomgr/ev_posix.c',
   'src/core/lib/iomgr/exec_ctx.c',
@@ -184,20 +183,28 @@
   '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/security/b64.c',
-  'src/core/lib/security/client_auth_filter.c',
-  'src/core/lib/security/credentials.c',
-  'src/core/lib/security/credentials_metadata.c',
-  'src/core/lib/security/credentials_posix.c',
-  'src/core/lib/security/credentials_win32.c',
-  'src/core/lib/security/google_default_credentials.c',
-  'src/core/lib/security/handshake.c',
-  'src/core/lib/security/json_token.c',
-  'src/core/lib/security/jwt_verifier.c',
-  'src/core/lib/security/secure_endpoint.c',
-  'src/core/lib/security/security_connector.c',
-  'src/core/lib/security/security_context.c',
-  'src/core/lib/security/server_auth_filter.c',
+  'src/core/lib/security/context/security_context.c',
+  'src/core/lib/security/credentials/composite/composite_credentials.c',
+  'src/core/lib/security/credentials/credentials.c',
+  'src/core/lib/security/credentials/credentials_metadata.c',
+  'src/core/lib/security/credentials/fake/fake_credentials.c',
+  'src/core/lib/security/credentials/google_default/credentials_posix.c',
+  'src/core/lib/security/credentials/google_default/credentials_win32.c',
+  'src/core/lib/security/credentials/google_default/google_default_credentials.c',
+  'src/core/lib/security/credentials/iam/iam_credentials.c',
+  'src/core/lib/security/credentials/jwt/json_token.c',
+  'src/core/lib/security/credentials/jwt/jwt_credentials.c',
+  'src/core/lib/security/credentials/jwt/jwt_verifier.c',
+  'src/core/lib/security/credentials/oauth2/oauth2_credentials.c',
+  'src/core/lib/security/credentials/plugin/plugin_credentials.c',
+  'src/core/lib/security/credentials/ssl/ssl_credentials.c',
+  'src/core/lib/security/transport/client_auth_filter.c',
+  'src/core/lib/security/transport/handshake.c',
+  'src/core/lib/security/transport/secure_endpoint.c',
+  'src/core/lib/security/transport/security_connector.c',
+  'src/core/lib/security/transport/server_auth_filter.c',
+  'src/core/lib/security/util/b64.c',
+  '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',
diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json
index 691062f..1beb619 100644
--- a/src/python/grpcio/tests/tests.json
+++ b/src/python/grpcio/tests/tests.json
@@ -5,6 +5,7 @@
   "_base_interface_test.SyncPeasyTest", 
   "_beta_features_test.BetaFeaturesTest", 
   "_beta_features_test.ContextManagementAndLifecycleTest", 
+  "_cancel_many_calls_test.CancelManyCallsTest",
   "_channel_test.ChannelTest", 
   "_connectivity_channel_test.ChannelConnectivityTest", 
   "_core_over_links_base_interface_test.AsyncEasyTest", 
diff --git a/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py
new file mode 100644
index 0000000..c1de779
--- /dev/null
+++ b/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py
@@ -0,0 +1,222 @@
+# 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.
+
+"""Test making many calls and immediately cancelling most of them."""
+
+import threading
+import unittest
+
+from grpc._cython import cygrpc
+from grpc.framework.foundation import logging_pool
+from tests.unit.framework.common import test_constants
+
+_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
+_EMPTY_FLAGS = 0
+_EMPTY_METADATA = cygrpc.Metadata(())
+
+_SERVER_SHUTDOWN_TAG = 'server_shutdown'
+_REQUEST_CALL_TAG = 'request_call'
+_RECEIVE_CLOSE_ON_SERVER_TAG = 'receive_close_on_server'
+_RECEIVE_MESSAGE_TAG = 'receive_message'
+_SERVER_COMPLETE_CALL_TAG = 'server_complete_call'
+
+_SUCCESS_CALL_FRACTION = 1.0 / 8.0
+
+
+class _State(object):
+
+  def __init__(self):
+    self.condition = threading.Condition()
+    self.handlers_released = False
+    self.parked_handlers = 0
+    self.handled_rpcs = 0
+
+
+def _is_cancellation_event(event):
+  return (
+      event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and
+      event.batch_operations[0].received_cancelled)
+
+
+class _Handler(object):
+
+  def __init__(self, state, completion_queue, rpc_event):
+    self._state = state
+    self._lock = threading.Lock()
+    self._completion_queue = completion_queue
+    self._call = rpc_event.operation_call
+
+  def __call__(self):
+    with self._state.condition:
+      self._state.parked_handlers += 1
+      if self._state.parked_handlers == test_constants.THREAD_CONCURRENCY:
+        self._state.condition.notify_all()
+      while not self._state.handlers_released:
+        self._state.condition.wait()
+
+    with self._lock:
+      self._call.start_batch(
+          cygrpc.Operations(
+              (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)),
+          _RECEIVE_CLOSE_ON_SERVER_TAG)
+      self._call.start_batch(
+          cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)),
+          _RECEIVE_MESSAGE_TAG)
+    first_event = self._completion_queue.poll()
+    if _is_cancellation_event(first_event):
+      self._completion_queue.poll()
+    else:
+      with self._lock:
+        operations = (
+            cygrpc.operation_send_initial_metadata(
+                _EMPTY_METADATA, _EMPTY_FLAGS),
+            cygrpc.operation_send_message(b'\x79\x57', _EMPTY_FLAGS),
+            cygrpc.operation_send_status_from_server(
+                _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!',
+                _EMPTY_FLAGS),
+        )
+        self._call.start_batch(
+            cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG)
+      self._completion_queue.poll()
+      self._completion_queue.poll()
+
+
+def _serve(state, server, server_completion_queue, thread_pool):
+  for _ in range(test_constants.RPC_CONCURRENCY):
+    call_completion_queue = cygrpc.CompletionQueue()
+    server.request_call(
+        call_completion_queue, server_completion_queue, _REQUEST_CALL_TAG)
+    rpc_event = server_completion_queue.poll()
+    thread_pool.submit(_Handler(state, call_completion_queue, rpc_event))
+    with state.condition:
+      state.handled_rpcs += 1
+      if test_constants.RPC_CONCURRENCY <= state.handled_rpcs:
+        state.condition.notify_all()
+  server_completion_queue.poll()
+
+
+class _QueueDriver(object):
+
+  def __init__(self, condition, completion_queue, due):
+    self._condition = condition
+    self._completion_queue = completion_queue
+    self._due = due
+    self._events = []
+    self._returned = False
+
+  def start(self):
+    def in_thread():
+      while True:
+        event = self._completion_queue.poll()
+        with self._condition:
+          self._events.append(event)
+          self._due.remove(event.tag)
+          self._condition.notify_all()
+          if not self._due:
+            self._returned = True
+            return
+    thread = threading.Thread(target=in_thread)
+    thread.start()
+
+  def events(self, at_least):
+    with self._condition:
+      while len(self._events) < at_least:
+        self._condition.wait()
+      return tuple(self._events)
+
+
+class CancelManyCallsTest(unittest.TestCase):
+
+  def testCancelManyCalls(self):
+    server_thread_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
+
+    server_completion_queue = cygrpc.CompletionQueue()
+    server = cygrpc.Server()
+    server.register_completion_queue(server_completion_queue)
+    port = server.add_http2_port('[::]:0')
+    server.start()
+    channel = cygrpc.Channel('localhost:{}'.format(port))
+
+    state = _State()
+
+    server_thread_args = (
+        state, server, server_completion_queue, server_thread_pool,)
+    server_thread = threading.Thread(target=_serve, args=server_thread_args)
+    server_thread.start()
+
+    client_condition = threading.Condition()
+    client_due = set()
+    client_completion_queue = cygrpc.CompletionQueue()
+    client_driver = _QueueDriver(
+        client_condition, client_completion_queue, client_due)
+    client_driver.start()
+
+    with client_condition:
+      client_calls = []
+      for index in range(test_constants.RPC_CONCURRENCY):
+        client_call = channel.create_call(
+            None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None,
+            _INFINITE_FUTURE)
+        operations = (
+            cygrpc.operation_send_initial_metadata(
+                _EMPTY_METADATA, _EMPTY_FLAGS),
+            cygrpc.operation_send_message(b'\x45\x56', _EMPTY_FLAGS),
+            cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
+            cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),
+            cygrpc.operation_receive_message(_EMPTY_FLAGS),
+            cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),
+        )
+        tag = 'client_complete_call_{0:04d}_tag'.format(index)
+        client_call.start_batch(cygrpc.Operations(operations), tag)
+        client_due.add(tag)
+        client_calls.append(client_call)
+
+    with state.condition:
+      while True:
+        if state.parked_handlers < test_constants.THREAD_CONCURRENCY:
+          state.condition.wait()
+        elif state.handled_rpcs < test_constants.RPC_CONCURRENCY:
+          state.condition.wait()
+        else:
+          state.handlers_released = True
+          state.condition.notify_all()
+          break
+
+    client_driver.events(
+        test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION)
+    with client_condition:
+      for client_call in client_calls:
+        client_call.cancel()
+
+    with state.condition:
+      server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG)
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 4bb615f..b6ddbe8 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -52,21 +52,41 @@
   grpc_event event;
   gpr_timespec timeout;
   void *tag;
+  volatile int interrupted;
 } next_call_stack;
 
 /* Calls grpc_completion_queue_next without holding the ruby GIL */
 static void *grpc_rb_completion_queue_next_no_gil(void *param) {
   next_call_stack *const next_call = (next_call_stack*)param;
-  next_call->event =
-      grpc_completion_queue_next(next_call->cq, next_call->timeout, NULL);
+  gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN);
+  gpr_timespec deadline;
+  do {
+    deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment);
+    next_call->event = grpc_completion_queue_next(next_call->cq,
+                                                  deadline, NULL);
+    if (next_call->event.type != GRPC_QUEUE_TIMEOUT ||
+        gpr_time_cmp(deadline, next_call->timeout) > 0) {
+      break;
+    }
+  } while (!next_call->interrupted);
   return NULL;
 }
 
 /* Calls grpc_completion_queue_pluck without holding the ruby GIL */
 static void *grpc_rb_completion_queue_pluck_no_gil(void *param) {
   next_call_stack *const next_call = (next_call_stack*)param;
-  next_call->event = grpc_completion_queue_pluck(next_call->cq, next_call->tag,
-                                                 next_call->timeout, NULL);
+  gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN);
+  gpr_timespec deadline;
+  do {
+    deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment);
+    next_call->event = grpc_completion_queue_pluck(next_call->cq,
+                                                   next_call->tag,
+                                                   deadline, NULL);
+    if (next_call->event.type != GRPC_QUEUE_TIMEOUT ||
+        gpr_time_cmp(deadline, next_call->timeout) > 0) {
+      break;
+    }
+  } while (!next_call->interrupted);
   return NULL;
 }
 
@@ -139,6 +159,11 @@
   return TypedData_Wrap_Struct(cls, &grpc_rb_completion_queue_data_type, cq);
 }
 
+static void unblock_func(void *param) {
+  next_call_stack *const next_call = (next_call_stack*)param;
+  next_call->interrupted = 1;
+}
+
 /* Blocks until the next event for given tag is available, and returns the
  * event. */
 grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
@@ -158,8 +183,23 @@
     next_call.tag = ROBJECT(tag);
   }
   next_call.event.type = GRPC_QUEUE_TIMEOUT;
-  rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil,
-                             (void *)&next_call, NULL, NULL);
+  /* Loop until we finish a pluck without an interruption. The internal
+     pluck function runs either until it is interrupted or it gets an
+     event, or time runs out.
+
+     The basic reason we need this relatively complicated construction is that
+     we need to re-acquire the GVL when an interrupt comes in, so that the ruby
+     interpreter can do what it needs to do with the interrupt. But we also need
+     to get back to plucking when the interrupt has been handled. */
+  do {
+    next_call.interrupted = 0;
+    rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil,
+                               (void *)&next_call, unblock_func,
+                               (void *)&next_call);
+    /* If an interrupt prevented pluck from returning useful information, then
+       any plucks that did complete must have timed out */
+  } while (next_call.interrupted &&
+           next_call.event.type == GRPC_QUEUE_TIMEOUT);
   return next_call.event;
 }
 
diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h
index 6cc4e96..42de43c 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.h
+++ b/src/ruby/ext/grpc/rb_completion_queue.h
@@ -46,7 +46,7 @@
  *
  * This avoids having code that holds the GIL repeated at multiple sites.
  */
-grpc_event grpc_rb_completion_queue_pluck_event(VALUE cqueue, VALUE tag,
+grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
                                                 VALUE timeout);
 
 /* Initializes the CompletionQueue class. */
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 5277148..06a07ac 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -50,7 +50,6 @@
 #include "rb_loader.h"
 #include "rb_server.h"
 #include "rb_server_credentials.h"
-#include "rb_signal.h"
 
 static VALUE grpc_rb_cTimeVal = Qnil;
 
@@ -333,7 +332,6 @@
   Init_grpc_channel_credentials();
   Init_grpc_server();
   Init_grpc_server_credentials();
-  Init_grpc_signals();
   Init_grpc_status_codes();
   Init_grpc_time_consts();
 }
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index cebbe8c..3b62984 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -115,6 +115,7 @@
 grpc_server_request_registered_call_type grpc_server_request_registered_call_import;
 grpc_server_create_type grpc_server_create_import;
 grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
+grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import;
 grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import;
 grpc_server_start_type grpc_server_start_import;
 grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import;
@@ -382,6 +383,7 @@
   grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call");
   grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create");
   grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue");
+  grpc_server_register_non_listening_completion_queue_import = (grpc_server_register_non_listening_completion_queue_type) GetProcAddress(library, "grpc_server_register_non_listening_completion_queue");
   grpc_server_add_insecure_http2_port_import = (grpc_server_add_insecure_http2_port_type) GetProcAddress(library, "grpc_server_add_insecure_http2_port");
   grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start");
   grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index d7ea6c5..1428e6d 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -296,6 +296,9 @@
 typedef void(*grpc_server_register_completion_queue_type)(grpc_server *server, grpc_completion_queue *cq, void *reserved);
 extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
 #define grpc_server_register_completion_queue grpc_server_register_completion_queue_import
+typedef void(*grpc_server_register_non_listening_completion_queue_type)(grpc_server *server, grpc_completion_queue *q, void *reserved);
+extern grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import;
+#define grpc_server_register_non_listening_completion_queue grpc_server_register_non_listening_completion_queue_import
 typedef int(*grpc_server_add_insecure_http2_port_type)(grpc_server *server, const char *addr);
 extern grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import;
 #define grpc_server_add_insecure_http2_port grpc_server_add_insecure_http2_port_import
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 2b3acaa..0899feb 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -60,6 +60,7 @@
   VALUE mark;
   /* The actual server */
   grpc_server *wrapped;
+  grpc_completion_queue *queue;
 } grpc_rb_server;
 
 /* Destroys server instances. */
@@ -145,6 +146,7 @@
   }
   grpc_server_register_completion_queue(srv, cq, NULL);
   wrapper->wrapped = srv;
+  wrapper->queue = cq;
 
   /* Add the cq as the server's mark object. This ensures the ruby cq can't be
      GCed before the server */
diff --git a/src/ruby/ext/grpc/rb_signal.c b/src/ruby/ext/grpc/rb_signal.c
deleted file mode 100644
index a9e5123..0000000
--- a/src/ruby/ext/grpc/rb_signal.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * 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 <ruby/ruby.h>
-#include <signal.h>
-#include <stdbool.h>
-
-#include <grpc/support/log.h>
-
-#include "rb_grpc.h"
-
-static void (*old_sigint_handler)(int);
-static void (*old_sigterm_handler)(int);
-
-static volatile bool signal_received = false;
-
-/* This has to be handled at the C level instead of Ruby, because Ruby signal
- * handlers are constrained to run in the main interpreter thread. If that main
- * thread is blocked on grpc_completion_queue_pluck, the signal handlers will
- * never run */
-static void handle_signal(int signum) {
-  signal_received = true;
-  if (signum == SIGINT) {
-    old_sigint_handler(signum);
-  } else if (signum == SIGTERM) {
-    old_sigterm_handler(signum);
-  }
-}
-
-static VALUE grpc_rb_signal_received(VALUE self) {
-  (void)self;
-  return signal_received ? Qtrue : Qfalse;
-}
-
-void Init_grpc_signals() {
-  old_sigint_handler = signal(SIGINT, handle_signal);
-  old_sigterm_handler = signal(SIGTERM, handle_signal);
-  rb_define_singleton_method(grpc_rb_mGrpcCore, "signal_received?",
-                             grpc_rb_signal_received, 0);
-}
diff --git a/src/ruby/ext/grpc/rb_signal.h b/src/ruby/ext/grpc/rb_signal.h
deleted file mode 100644
index 07e49c0..0000000
--- a/src/ruby/ext/grpc/rb_signal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * 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_RB_SIGNAL_H_
-#define GRPC_RB_SIGNAL_H_
-
-void Init_grpc_signals();
-
-#endif  /* GRPC_RB_SIGNAL_H_ */
diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb
index 7c9aae3..79fa705 100644
--- a/src/ruby/lib/grpc.rb
+++ b/src/ruby/lib/grpc.rb
@@ -33,7 +33,6 @@
 require_relative 'grpc/grpc'
 require_relative 'grpc/logconfig'
 require_relative 'grpc/notifier'
-require_relative 'grpc/signals'
 require_relative 'grpc/version'
 require_relative 'grpc/core/time_consts'
 require_relative 'grpc/generic/active_call'
@@ -48,5 +47,3 @@
 ensure
   file.close
 end
-
-GRPC::Signals.wait_for_signals
diff --git a/src/ruby/lib/grpc/errors.rb b/src/ruby/lib/grpc/errors.rb
index a1dd1e3..23b2bb7 100644
--- a/src/ruby/lib/grpc/errors.rb
+++ b/src/ruby/lib/grpc/errors.rb
@@ -40,11 +40,12 @@
 
     # @param code [Numeric] the status code
     # @param details [String] the details of the exception
-    def initialize(code, details = 'unknown cause', **kw)
+    # @param metadata [Hash] the error's metadata
+    def initialize(code, details = 'unknown cause', metadata = {})
       super("#{code}:#{details}")
       @code = code
       @details = details
-      @metadata = kw
+      @metadata = metadata
     end
 
     # Converts the exception to a GRPC::Status for use in the networking
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index fd20a86..e449e89 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -30,7 +30,6 @@
 require 'forwardable'
 require 'weakref'
 require_relative 'bidi_call'
-require_relative '../signals'
 
 class Struct
   # BatchResult is the struct returned by calls to call#start_batch.
@@ -45,7 +44,7 @@
         # raise BadStatus, propagating the metadata if present.
         md = status.metadata
         with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }]
-        fail GRPC::BadStatus.new(status.code, status.details, **with_sym_keys)
+        fail GRPC::BadStatus.new(status.code, status.details, with_sym_keys)
       end
       status
     end
@@ -77,14 +76,15 @@
     #
     # @param call [Call] a call on which to start and invocation
     # @param q [CompletionQueue] the completion queue
-    def self.client_invoke(call, q, **kw)
+    # @param metadata [Hash] the metadata
+    def self.client_invoke(call, q, metadata = {})
       fail(TypeError, '!Core::Call') unless call.is_a? Core::Call
       unless q.is_a? Core::CompletionQueue
         fail(TypeError, '!Core::CompletionQueue')
       end
       metadata_tag = Object.new
       call.run_batch(q, metadata_tag, INFINITE_FUTURE,
-                     SEND_INITIAL_METADATA => kw)
+                     SEND_INITIAL_METADATA => metadata)
       metadata_tag
     end
 
@@ -123,10 +123,6 @@
       @unmarshal = unmarshal
       @metadata_tag = metadata_tag
       @op_notifier = nil
-      weak_self = WeakRef.new(self)
-      remove_handler = GRPC::Signals.register_handler(&weak_self
-                                                        .method(:cancel))
-      ObjectSpace.define_finalizer(self, remove_handler)
     end
 
     # output_metadata are provides access to hash that can be used to
@@ -216,13 +212,12 @@
     # @param details [String] details
     # @param assert_finished [true, false] when true(default), waits for
     # FINISHED.
-    #
-    # == Keyword Arguments ==
-    # any keyword arguments are treated as metadata to be sent to the server
-    # if a keyword value is a list, multiple metadata for it's key are sent
-    def send_status(code = OK, details = '', assert_finished = false, **kw)
+    # @param metadata [Hash] metadata to send to the server. If a value is a
+    # list, mulitple metadata for its key are sent
+    def send_status(code = OK, details = '', assert_finished = false,
+                    metadata: {})
       ops = {
-        SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, kw)
+        SEND_STATUS_FROM_SERVER => Struct::Status.new(code, details, metadata)
       }
       ops[RECV_CLOSE_ON_SERVER] = nil if assert_finished
       @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
@@ -316,14 +311,12 @@
     # request_response sends a request to a GRPC server, and returns the
     # response.
     #
-    # == Keyword Arguments ==
-    # any keyword arguments are treated as metadata to be sent to the server
-    # if a keyword value is a list, multiple metadata for it's key are sent
-    #
     # @param req [Object] the request sent to the server
+    # @param metadata [Hash] metadata to be sent to the server. If a value is
+    # a list, multiple metadata for its key are sent
     # @return [Object] the response received from the server
-    def request_response(req, **kw)
-      start_call(**kw) unless @started
+    def request_response(req, metadata: {})
+      start_call(metadata) unless @started
       remote_send(req)
       writes_done(false)
       response = remote_read
@@ -342,14 +335,12 @@
     # array of marshallable objects; in typical case it will be an Enumerable
     # that allows dynamic construction of the marshallable objects.
     #
-    # == Keyword Arguments ==
-    # any keyword arguments are treated as metadata to be sent to the server
-    # if a keyword value is a list, multiple metadata for it's key are sent
-    #
     # @param requests [Object] an Enumerable of requests to send
+    # @param metadata [Hash] metadata to be sent to the server. If a value is
+    # a list, multiple metadata for its key are sent
     # @return [Object] the response received from the server
-    def client_streamer(requests, **kw)
-      start_call(**kw) unless @started
+    def client_streamer(requests, metadata: {})
+      start_call(metadata) unless @started
       requests.each { |r| remote_send(r) }
       writes_done(false)
       response = remote_read
@@ -370,15 +361,12 @@
     # it is executed with each response as the argument and no result is
     # returned.
     #
-    # == Keyword Arguments ==
-    # any keyword arguments are treated as metadata to be sent to the server
-    # if a keyword value is a list, multiple metadata for it's key are sent
-    # any keyword arguments are treated as metadata to be sent to the server.
-    #
     # @param req [Object] the request sent to the server
+    # @param metadata [Hash] metadata to be sent to the server. If a value is
+    # a list, multiple metadata for its key are sent
     # @return [Enumerator|nil] a response Enumerator
-    def server_streamer(req, **kw)
-      start_call(**kw) unless @started
+    def server_streamer(req, metadata: {})
+      start_call(metadata) unless @started
       remote_send(req)
       writes_done(false)
       replies = enum_for(:each_remote_read_then_finish)
@@ -412,14 +400,12 @@
     # the_call#writes_done has been called, otherwise the block will loop
     # forever.
     #
-    # == Keyword Arguments ==
-    # any keyword arguments are treated as metadata to be sent to the server
-    # if a keyword value is a list, multiple metadata for it's key are sent
-    #
     # @param requests [Object] an Enumerable of requests to send
+    # @param metadata [Hash] metadata to be sent to the server. If a value is
+    # a list, multiple metadata for its key are sent
     # @return [Enumerator, nil] a response Enumerator
-    def bidi_streamer(requests, **kw, &blk)
-      start_call(**kw) unless @started
+    def bidi_streamer(requests, metadata: {}, &blk)
+      start_call(metadata) unless @started
       bd = BidiCall.new(@call, @cq, @marshal, @unmarshal,
                         metadata_tag: @metadata_tag)
       @metadata_tag = nil  # run_on_client ensures metadata is read
@@ -458,9 +444,11 @@
     private
 
     # Starts the call if not already started
-    def start_call(**kw)
+    # @param metadata [Hash] metadata to be sent to the server. If a value is
+    # a list, multiple metadata for its key are sent
+    def start_call(metadata = {})
       return if @started
-      @metadata_tag = ActiveCall.client_invoke(@call, @cq, **kw)
+      @metadata_tag = ActiveCall.client_invoke(@call, @cq, metadata)
       @started = true
     end
 
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 12946fe..cddca13 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -44,21 +44,21 @@
 
     # setup_channel is used by #initialize to constuct a channel from its
     # arguments.
-    def self.setup_channel(alt_chan, host, creds, **kw)
+    def self.setup_channel(alt_chan, host, creds, channel_args = {})
       unless alt_chan.nil?
         fail(TypeError, '!Channel') unless alt_chan.is_a?(Core::Channel)
         return alt_chan
       end
-      if kw['grpc.primary_user_agent'].nil?
-        kw['grpc.primary_user_agent'] = ''
+      if channel_args['grpc.primary_user_agent'].nil?
+        channel_args['grpc.primary_user_agent'] = ''
       else
-        kw['grpc.primary_user_agent'] += ' '
+        channel_args['grpc.primary_user_agent'] += ' '
       end
-      kw['grpc.primary_user_agent'] += "grpc-ruby/#{VERSION}"
+      channel_args['grpc.primary_user_agent'] += "grpc-ruby/#{VERSION}"
       unless creds.is_a?(Core::ChannelCredentials) || creds.is_a?(Symbol)
         fail(TypeError, '!ChannelCredentials or Symbol')
       end
-      Core::Channel.new(host, kw, creds)
+      Core::Channel.new(host, channel_args, creds)
     end
 
     # Allows users of the stub to modify the propagate mask.
@@ -96,15 +96,16 @@
     #     :this_channel_is_insecure
     # @param channel_override [Core::Channel] a pre-created channel
     # @param timeout [Number] the default timeout to use in requests
-    # @param kw [KeywordArgs]the channel arguments
+    # @param channel_args [Hash] the channel arguments
     def initialize(host, q, creds,
                    channel_override: nil,
                    timeout: nil,
                    propagate_mask: nil,
-                   **kw)
+                   channel_args: {})
       fail(TypeError, '!CompletionQueue') unless q.is_a?(Core::CompletionQueue)
-      @ch = ClientStub.setup_channel(channel_override, host, creds, **kw)
-      alt_host = kw[Core::Channel::SSL_TARGET]
+      @ch = ClientStub.setup_channel(channel_override, host, creds,
+                                     channel_args)
+      alt_host = channel_args[Core::Channel::SSL_TARGET]
       @host = alt_host.nil? ? host : alt_host
       @propagate_mask = propagate_mask
       @timeout = timeout.nil? ? DEFAULT_TIMEOUT : timeout
@@ -135,42 +136,35 @@
     # If return_op is true, the call returns an Operation, calling execute
     # on the Operation returns the response.
     #
-    # == Keyword Args ==
-    #
-    # Unspecified keyword arguments are treated as metadata to be sent to the
-    # server.
-    #
     # @param method [String] the RPC method to call on the GRPC server
     # @param req [Object] the request sent to the server
     # @param marshal [Function] f(obj)->string that marshals requests
     # @param unmarshal [Function] f(string)->obj that unmarshals responses
-    # @param timeout [Numeric] (optional) the max completion time in seconds
     # @param deadline [Time] (optional) the time the request should complete
+    # @param return_op [true|false] return an Operation if true
     # @param parent [Core::Call] a prior call whose reserved metadata
     #   will be propagated by this one.
     # @param credentials [Core::CallCredentials] credentials to use when making
     #   the call
-    # @param return_op [true|false] return an Operation if true
+    # @param metadata [Hash] metadata to be sent to the server
     # @return [Object] the response received from the server
     def request_response(method, req, marshal, unmarshal,
                          deadline: nil,
-                         timeout: nil,
                          return_op: false,
                          parent: nil,
                          credentials: nil,
-                         **kw)
+                         metadata: {})
       c = new_active_call(method, marshal, unmarshal,
                           deadline: deadline,
-                          timeout: timeout,
                           parent: parent,
                           credentials: credentials)
-      return c.request_response(req, **kw) unless return_op
+      return c.request_response(req, metadata: metadata) unless return_op
 
       # return the operation view of the active_call; define #execute as a
       # new method for this instance that invokes #request_response.
       op = c.operation
       op.define_singleton_method(:execute) do
-        c.request_response(req, **kw)
+        c.request_response(req, metadata: metadata)
       end
       op
     end
@@ -205,42 +199,35 @@
     #
     # If return_op is true, the call returns the response.
     #
-    # == Keyword Args ==
-    #
-    # Unspecified keyword arguments are treated as metadata to be sent to the
-    # server.
-    #
     # @param method [String] the RPC method to call on the GRPC server
     # @param requests [Object] an Enumerable of requests to send
     # @param marshal [Function] f(obj)->string that marshals requests
     # @param unmarshal [Function] f(string)->obj that unmarshals responses
-    # @param timeout [Numeric] (optional) the max completion time in seconds
     # @param deadline [Time] (optional) the time the request should complete
     # @param return_op [true|false] return an Operation if true
     # @param parent [Core::Call] a prior call whose reserved metadata
     #   will be propagated by this one.
     # @param credentials [Core::CallCredentials] credentials to use when making
     #   the call
+    # @param metadata [Hash] metadata to be sent to the server
     # @return [Object|Operation] the response received from the server
     def client_streamer(method, requests, marshal, unmarshal,
                         deadline: nil,
-                        timeout: nil,
                         return_op: false,
                         parent: nil,
                         credentials: nil,
-                        **kw)
+                        metadata: {})
       c = new_active_call(method, marshal, unmarshal,
                           deadline: deadline,
-                          timeout: timeout,
                           parent: parent,
                           credentials: credentials)
-      return c.client_streamer(requests, **kw) unless return_op
+      return c.client_streamer(requests, metadata: metadata) unless return_op
 
       # return the operation view of the active_call; define #execute as a
       # new method for this instance that invokes #client_streamer.
       op = c.operation
       op.define_singleton_method(:execute) do
-        c.client_streamer(requests, **kw)
+        c.client_streamer(requests, metadata: metadata)
       end
       op
     end
@@ -292,35 +279,33 @@
     # @param req [Object] the request sent to the server
     # @param marshal [Function] f(obj)->string that marshals requests
     # @param unmarshal [Function] f(string)->obj that unmarshals responses
-    # @param timeout [Numeric] (optional) the max completion time in seconds
     # @param deadline [Time] (optional) the time the request should complete
     # @param return_op [true|false]return an Operation if true
     # @param parent [Core::Call] a prior call whose reserved metadata
     #   will be propagated by this one.
     # @param credentials [Core::CallCredentials] credentials to use when making
     #   the call
+    # @param metadata [Hash] metadata to be sent to the server
     # @param blk [Block] when provided, is executed for each response
     # @return [Enumerator|Operation|nil] as discussed above
     def server_streamer(method, req, marshal, unmarshal,
                         deadline: nil,
-                        timeout: nil,
                         return_op: false,
                         parent: nil,
                         credentials: nil,
-                        **kw,
+                        metadata: {},
                         &blk)
       c = new_active_call(method, marshal, unmarshal,
                           deadline: deadline,
-                          timeout: timeout,
                           parent: parent,
                           credentials: credentials)
-      return c.server_streamer(req, **kw, &blk) unless return_op
+      return c.server_streamer(req, metadata: metadata, &blk) unless return_op
 
       # return the operation view of the active_call; define #execute
       # as a new method for this instance that invokes #server_streamer
       op = c.operation
       op.define_singleton_method(:execute) do
-        c.server_streamer(req, **kw, &blk)
+        c.server_streamer(req, metadata: metadata, &blk)
       end
       op
     end
@@ -391,11 +376,6 @@
     # * the deadline is exceeded
     #
     #
-    # == Keyword Args ==
-    #
-    # Unspecified keyword arguments are treated as metadata to be sent to the
-    # server.
-    #
     # == Return Value ==
     #
     # if the return_op is false, the return value is an Enumerator of the
@@ -411,36 +391,35 @@
     # @param requests [Object] an Enumerable of requests to send
     # @param marshal [Function] f(obj)->string that marshals requests
     # @param unmarshal [Function] f(string)->obj that unmarshals responses
-    # @param timeout [Numeric] (optional) the max completion time in seconds
     # @param deadline [Time] (optional) the time the request should complete
     # @param parent [Core::Call] a prior call whose reserved metadata
     #   will be propagated by this one.
     # @param credentials [Core::CallCredentials] credentials to use when making
     #   the call
     # @param return_op [true|false] return an Operation if true
+    # @param metadata [Hash] metadata to be sent to the server
     # @param blk [Block] when provided, is executed for each response
     # @return [Enumerator|nil|Operation] as discussed above
     def bidi_streamer(method, requests, marshal, unmarshal,
                       deadline: nil,
-                      timeout: nil,
                       return_op: false,
                       parent: nil,
                       credentials: nil,
-                      **kw,
+                      metadata: {},
                       &blk)
       c = new_active_call(method, marshal, unmarshal,
                           deadline: deadline,
-                          timeout: timeout,
                           parent: parent,
                           credentials: credentials)
 
-      return c.bidi_streamer(requests, **kw, &blk) unless return_op
+      return c.bidi_streamer(requests, metadata: metadata,
+                             &blk) unless return_op
 
       # return the operation view of the active_call; define #execute
       # as a new method for this instance that invokes #bidi_streamer
       op = c.operation
       op.define_singleton_method(:execute) do
-        c.bidi_streamer(requests, **kw, &blk)
+        c.bidi_streamer(requests, metadata: metadata, &blk)
       end
       op
     end
@@ -457,12 +436,10 @@
     # @param timeout [TimeConst]
     def new_active_call(method, marshal, unmarshal,
                         deadline: nil,
-                        timeout: nil,
                         parent: nil,
                         credentials: nil)
-      if deadline.nil?
-        deadline = from_relative_time(timeout.nil? ? @timeout : timeout)
-      end
+
+      deadline = from_relative_time(@timeout) if deadline.nil?
       # Provide each new client call with its own completion queue
       call_queue = Core::CompletionQueue.new
       call = @ch.create_call(call_queue,
diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb
index cc21ffd..913f55d 100644
--- a/src/ruby/lib/grpc/generic/rpc_desc.rb
+++ b/src/ruby/lib/grpc/generic/rpc_desc.rb
@@ -80,12 +80,12 @@
       else  # is a bidi_stream
         active_call.run_server_bidi(mth)
       end
-      send_status(active_call, OK, 'OK', **active_call.output_metadata)
+      send_status(active_call, OK, 'OK', active_call.output_metadata)
     rescue BadStatus => e
       # this is raised by handlers that want GRPC to send an application error
       # code and detail message and some additional app-specific metadata.
       GRPC.logger.debug("app err:#{active_call}, status:#{e.code}:#{e.details}")
-      send_status(active_call, e.code, e.details, **e.metadata)
+      send_status(active_call, e.code, e.details, e.metadata)
     rescue Core::CallError => e
       # This is raised by GRPC internals but should rarely, if ever happen.
       # Log it, but don't notify the other endpoint..
@@ -135,10 +135,10 @@
       "##{mth.name}: bad arg count; got:#{mth.arity}, want:#{want}, #{msg}"
     end
 
-    def send_status(active_client, code, details, **kw)
+    def send_status(active_client, code, details, metadata = {})
       details = 'Not sure why' if details.nil?
       GRPC.logger.debug("Sending status  #{code}:#{details}")
-      active_client.send_status(code, details, code == OK, **kw)
+      active_client.send_status(code, details, code == OK, metadata: metadata)
     rescue StandardError => e
       GRPC.logger.warn("Could not send status #{code}:#{details}")
       GRPC.logger.warn(e)
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 238aaa9..6b0b4ce 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -28,7 +28,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require_relative '../grpc'
-require_relative '../signals'
 require_relative 'active_call'
 require_relative 'service'
 require 'thread'
@@ -170,14 +169,6 @@
       alt_cq
     end
 
-    # setup_srv is used by #initialize to constuct a Core::Server from its
-    # arguments.
-    def self.setup_srv(alt_srv, cq, **kw)
-      return Core::Server.new(cq, kw) if alt_srv.nil?
-      fail(TypeError, '!Server') unless alt_srv.is_a? Core::Server
-      alt_srv
-    end
-
     # setup_connect_md_proc is used by #initialize to validate the
     # connect_md_proc.
     def self.setup_connect_md_proc(a_proc)
@@ -194,9 +185,6 @@
     # instance, however other arbitrary are allowed and when present are used
     # to configure the listeninng connection set up by the RpcServer.
     #
-    # * server_override: which if passed must be a [GRPC::Core::Server].  When
-    # present.
-    #
     # * poll_period: when present, the server polls for new events with this
     # period
     #
@@ -218,13 +206,15 @@
     # when non-nil is a proc for determining metadata to to send back the client
     # on receiving an invocation req.  The proc signature is:
     # {key: val, ..} func(method_name, {key: val, ...})
+    #
+    # * server_args:
+    # A server arguments hash to be passed down to the underlying core server
     def initialize(pool_size:DEFAULT_POOL_SIZE,
                    max_waiting_requests:DEFAULT_MAX_WAITING_REQUESTS,
                    poll_period:DEFAULT_POLL_PERIOD,
                    completion_queue_override:nil,
-                   server_override:nil,
                    connect_md_proc:nil,
-                   **kw)
+                   server_args:{})
       @connect_md_proc = RpcServer.setup_connect_md_proc(connect_md_proc)
       @cq = RpcServer.setup_cq(completion_queue_override)
       @max_waiting_requests = max_waiting_requests
@@ -236,7 +226,7 @@
       # running_state can take 4 values: :not_started, :running, :stopping, and
       # :stopped. State transitions can only proceed in that order.
       @running_state = :not_started
-      @server = RpcServer.setup_srv(server_override, @cq, **kw)
+      @server = Core::Server.new(@cq, server_args)
     end
 
     # stops a running server
@@ -353,10 +343,7 @@
         transition_running_state(:running)
         @run_cond.broadcast
       end
-      remove_signal_handler = GRPC::Signals.register_handler { stop }
       loop_handle_server_calls
-      # Remove signal handler when server stops
-      remove_signal_handler.call
     end
 
     alias_method :run_till_terminated, :run
diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb
index 0a166e8..f30242e 100644
--- a/src/ruby/lib/grpc/generic/service.rb
+++ b/src/ruby/lib/grpc/generic/service.rb
@@ -179,24 +179,24 @@
             unmarshal = desc.unmarshal_proc(:output)
             route = "/#{route_prefix}/#{name}"
             if desc.request_response?
-              define_method(mth_name) do |req, **kw|
+              define_method(mth_name) do |req, metadata = {}|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                request_response(route, req, marshal, unmarshal, **kw)
+                request_response(route, req, marshal, unmarshal, metadata)
               end
             elsif desc.client_streamer?
-              define_method(mth_name) do |reqs, **kw|
+              define_method(mth_name) do |reqs, metadata = {}|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                client_streamer(route, reqs, marshal, unmarshal, **kw)
+                client_streamer(route, reqs, marshal, unmarshal, metadata)
               end
             elsif desc.server_streamer?
-              define_method(mth_name) do |req, **kw, &blk|
+              define_method(mth_name) do |req, metadata = {}, &blk|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                server_streamer(route, req, marshal, unmarshal, **kw, &blk)
+                server_streamer(route, req, marshal, unmarshal, metadata, &blk)
               end
             else  # is a bidi_stream
-              define_method(mth_name) do |reqs, **kw, &blk|
+              define_method(mth_name) do |reqs, metadata = {}, &blk|
                 GRPC.logger.debug("calling #{@host}:#{route}")
-                bidi_streamer(route, reqs, marshal, unmarshal, **kw, &blk)
+                bidi_streamer(route, reqs, marshal, unmarshal, metadata, &blk)
               end
             end
           end
diff --git a/src/ruby/lib/grpc/signals.rb b/src/ruby/lib/grpc/signals.rb
deleted file mode 100644
index 2ab85c8..0000000
--- a/src/ruby/lib/grpc/signals.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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.
-
-require 'thread'
-require_relative 'grpc'
-
-# GRPC contains the General RPC module.
-module GRPC
-  # Signals contains gRPC functions related to signal handling
-  module Signals
-    @interpreter_exiting = false
-    @signal_handlers = []
-    @handlers_mutex = Mutex.new
-
-    def register_handler(&handler)
-      @handlers_mutex.synchronize do
-        @signal_handlers.push(handler)
-        handler.call if @exit_signal_received
-      end
-      # Returns a function to remove the handler
-      lambda do
-        @handlers_mutex.synchronize { @signal_handlers.delete(handler) }
-      end
-    end
-    module_function :register_handler
-
-    def wait_for_signals
-      t = Thread.new do
-        sleep 0.1 until GRPC::Core.signal_received? || @interpreter_exiting
-        unless @interpreter_exiting
-          @handlers_mutex.synchronize do
-            @signal_handlers.each(&:call)
-          end
-        end
-      end
-      at_exit do
-        @interpreter_exiting = true
-        t.join
-      end
-    end
-    module_function :wait_for_signals
-  end
-end
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 95b059a..b669548 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -114,7 +114,9 @@
   if opts.secure
     creds = ssl_creds(opts.use_test_ca)
     stub_opts = {
-      GRPC::Core::Channel::SSL_TARGET => opts.host_override
+      channel_args: {
+        GRPC::Core::Channel::SSL_TARGET => opts.host_override
+      }
     }
 
     # Add service account creds if specified
@@ -315,7 +317,8 @@
   def timeout_on_sleeping_server
     msg_sizes = [[27_182, 31_415]]
     ppp = PingPongPlayer.new(msg_sizes)
-    resps = @stub.full_duplex_call(ppp.each_item, timeout: 0.001)
+    deadline = GRPC::Core::TimeConsts::from_relative_time(0.001)
+    resps = @stub.full_duplex_call(ppp.each_item, deadline: deadline)
     resps.each { |r| ppp.queue.push(r) }
     fail 'Should have raised GRPC::BadStatus(DEADLINE_EXCEEDED)'
   rescue GRPC::BadStatus => e
diff --git a/src/ruby/qps/client.rb b/src/ruby/qps/client.rb
index d04f707..917b012 100644
--- a/src/ruby/qps/client.rb
+++ b/src/ruby/qps/client.rb
@@ -66,8 +66,10 @@
         cred = GRPC::Core::ChannelCredentials.new()
       end
       if config.security_params.server_host_override
-        opts[GRPC::Core::Channel::SSL_TARGET] =
+        channel_args = {}
+        channel_args[GRPC::Core::Channel::SSL_TARGET] =
           config.security_params.server_host_override
+        opts[:channel_args] = channel_args
       end
     else
       cred = :this_channel_is_insecure
diff --git a/src/ruby/qps/server.rb b/src/ruby/qps/server.rb
index f05fbbd..52a89ce 100644
--- a/src/ruby/qps/server.rb
+++ b/src/ruby/qps/server.rb
@@ -75,13 +75,14 @@
     @port = @server.add_http2_port("0.0.0.0:" + port.to_s, cred)
     @server.handle(BenchmarkServiceImpl.new)
     @start_time = Time.now
-    Thread.new {
+    t = Thread.new {
       @server.run
     }
+    t.abort_on_exception
   end
   def mark(reset)
     s = Grpc::Testing::ServerStats.new(time_elapsed:
-                                         (Time.now-@start_time).to_f)
+                                       (Time.now-@start_time).to_f)
     @start_time = Time.now if reset
     s
   end
diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb
index c0181e2..d9c9780 100644
--- a/src/ruby/spec/generic/active_call_spec.rb
+++ b/src/ruby/spec/generic/active_call_spec.rb
@@ -159,9 +159,10 @@
   end
 
   describe '#client_invoke' do
-    it 'sends keywords as metadata to the server when the are present' do
+    it 'sends metadata to the server when present' do
       call = make_test_call
-      ActiveCall.client_invoke(call, @client_queue, k1: 'v1', k2: 'v2')
+      metadata = { k1: 'v1', k2: 'v2' }
+      ActiveCall.client_invoke(call, @client_queue, metadata)
       recvd_rpc =  @server.request_call(@server_queue, @server_tag, deadline)
       recvd_call = recvd_rpc.call
       expect(recvd_call).to_not be_nil
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index dd8e2e9..168e7fb 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -68,15 +68,7 @@
   describe '#new' do
     let(:fake_host) { 'localhost:0' }
     it 'can be created from a host and args' do
-      opts = { a_channel_arg: 'an_arg' }
-      blk = proc do
-        GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
-      end
-      expect(&blk).not_to raise_error
-    end
-
-    it 'can be created with a default deadline' do
-      opts = { a_channel_arg: 'an_arg', deadline: 5 }
+      opts = { channel_args: { a_channel_arg: 'an_arg' } }
       blk = proc do
         GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
       end
@@ -84,7 +76,10 @@
     end
 
     it 'can be created with an channel override' do
-      opts = { a_channel_arg: 'an_arg', channel_override: @ch }
+      opts = {
+        channel_args: { a_channel_arg: 'an_arg' },
+        channel_override: @ch
+      }
       blk = proc do
         GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
       end
@@ -93,7 +88,10 @@
 
     it 'cannot be created with a bad channel override' do
       blk = proc do
-        opts = { a_channel_arg: 'an_arg', channel_override: Object.new }
+        opts = {
+          channel_args: { a_channel_arg: 'an_arg' },
+          channel_override: Object.new
+        }
         GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
       end
       expect(&blk).to raise_error
@@ -101,7 +99,7 @@
 
     it 'cannot be created with bad credentials' do
       blk = proc do
-        opts = { a_channel_arg: 'an_arg' }
+        opts = { channel_args: { a_channel_arg: 'an_arg' } }
         GRPC::ClientStub.new(fake_host, @cq, Object.new, **opts)
       end
       expect(&blk).to raise_error
@@ -111,8 +109,10 @@
       certs = load_test_certs
       blk = proc do
         opts = {
-          GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
-          a_channel_arg: 'an_arg'
+          channel_args: {
+            GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
+            a_channel_arg: 'an_arg'
+          }
         }
         creds = GRPC::Core::ChannelCredentials.new(certs[0], nil, nil)
         GRPC::ClientStub.new(fake_host, @cq, creds,  **opts)
@@ -172,7 +172,7 @@
     describe 'without a call operation' do
       def get_response(stub)
         stub.request_response(@method, @sent_msg, noop, noop,
-                              k1: 'v1', k2: 'v2')
+                              metadata: { k1: 'v1', k2: 'v2' })
       end
 
       it_behaves_like 'request response'
@@ -181,7 +181,8 @@
     describe 'via a call operation' do
       def get_response(stub)
         op = stub.request_response(@method, @sent_msg, noop, noop,
-                                   return_op: true, k1: 'v1', k2: 'v2')
+                                   return_op: true,
+                                   metadata: { k1: 'v1', k2: 'v2' })
         expect(op).to be_a(GRPC::ActiveCall::Operation)
         op.execute
       end
@@ -196,7 +197,7 @@
         server_port = create_test_server
         host = "localhost:#{server_port}"
         @stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
-        @options = { k1: 'v1', k2: 'v2' }
+        @metadata = { k1: 'v1', k2: 'v2' }
         @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
         @resp = 'a_reply'
       end
@@ -208,7 +209,7 @@
       end
 
       it 'should send metadata to the server ok' do
-        th = run_client_streamer(@sent_msgs, @resp, @pass, @options)
+        th = run_client_streamer(@sent_msgs, @resp, @pass, **@metadata)
         expect(get_response(@stub)).to eq(@resp)
         th.join
       end
@@ -221,7 +222,7 @@
       end
 
       it 'should raise ArgumentError if metadata contains invalid values' do
-        @options.merge!(k3: 3)
+        @metadata.merge!(k3: 3)
         expect do
           get_response(@stub)
         end.to raise_error(ArgumentError,
@@ -231,7 +232,8 @@
 
     describe 'without a call operation' do
       def get_response(stub)
-        stub.client_streamer(@method, @sent_msgs, noop, noop, @options)
+        stub.client_streamer(@method, @sent_msgs, noop, noop,
+                             metadata: @metadata)
       end
 
       it_behaves_like 'client streaming'
@@ -240,7 +242,7 @@
     describe 'via a call operation' do
       def get_response(stub)
         op = stub.client_streamer(@method, @sent_msgs, noop, noop,
-                                  @options.merge(return_op: true))
+                                  return_op: true, metadata: @metadata)
         expect(op).to be_a(GRPC::ActiveCall::Operation)
         op.execute
       end
@@ -290,7 +292,7 @@
     describe 'without a call operation' do
       def get_responses(stub)
         e = stub.server_streamer(@method, @sent_msg, noop, noop,
-                                 k1: 'v1', k2: 'v2')
+                                 metadata: { k1: 'v1', k2: 'v2' })
         expect(e).to be_a(Enumerator)
         e
       end
@@ -301,7 +303,8 @@
     describe 'via a call operation' do
       def get_responses(stub)
         op = stub.server_streamer(@method, @sent_msg, noop, noop,
-                                  return_op: true, k1: 'v1', k2: 'v2')
+                                  return_op: true,
+                                  metadata: { k1: 'v1', k2: 'v2' })
         expect(op).to be_a(GRPC::ActiveCall::Operation)
         e = op.execute
         expect(e).to be_a(Enumerator)
@@ -383,7 +386,7 @@
         stub = GRPC::ClientStub.new(@host, @cq, :this_channel_is_insecure)
         blk = proc do
           e = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
-                                 timeout: 0.001)
+                                 deadline: from_relative_time(0.001))
           e.collect { |r| r }
         end
         expect(&blk).to raise_error GRPC::BadStatus, /Deadline Exceeded/
diff --git a/src/ruby/spec/generic/rpc_desc_spec.rb b/src/ruby/spec/generic/rpc_desc_spec.rb
index 083632a..d2080b7 100644
--- a/src/ruby/spec/generic/rpc_desc_spec.rb
+++ b/src/ruby/spec/generic/rpc_desc_spec.rb
@@ -56,14 +56,14 @@
     it 'sends the specified status if BadStatus is raised' do
       expect(@call).to receive(:remote_read).once.and_return(Object.new)
       expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
-                                                       {})
+                                                       metadata: {})
       this_desc.run_server_method(@call, method(:bad_status))
     end
 
     it 'sends status UNKNOWN if other StandardErrors are raised' do
       expect(@call).to receive(:remote_read).once.and_return(Object.new)
       expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason,
-                                                        false, {})
+                                                        false, metadata: {})
       this_desc.run_server_method(@call, method(:other_error))
     end
 
@@ -93,7 +93,7 @@
         expect(@call).to receive(:remote_send).once.with(@ok_response)
         expect(@call).to receive(:output_metadata).and_return(fake_md)
         expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
-                                                         **fake_md)
+                                                         metadata: fake_md)
         this_desc.run_server_method(@call, method(:fake_reqresp))
       end
     end
@@ -106,13 +106,13 @@
 
       it 'sends the specified status if BadStatus is raised' do
         expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
-                                                         {})
+                                                         metadata: {})
         @client_streamer.run_server_method(@call, method(:bad_status_alt))
       end
 
       it 'sends status UNKNOWN if other StandardErrors are raised' do
-        expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason,
-                                                          false, {})
+        expect(@call).to receive(:send_status).once.with(UNKNOWN, @no_reason,
+                                                         false, metadata: {})
         @client_streamer.run_server_method(@call, method(:other_error_alt))
       end
 
@@ -128,7 +128,7 @@
         expect(@call).to receive(:remote_send).once.with(@ok_response)
         expect(@call).to receive(:output_metadata).and_return(fake_md)
         expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
-                                                         **fake_md)
+                                                         metadata: fake_md)
         @client_streamer.run_server_method(@call, method(:fake_clstream))
       end
     end
@@ -148,7 +148,7 @@
         expect(@call).to receive(:remote_send).twice.with(@ok_response)
         expect(@call).to receive(:output_metadata).and_return(fake_md)
         expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
-                                                         **fake_md)
+                                                         metadata: fake_md)
         @server_streamer.run_server_method(@call, method(:fake_svstream))
       end
     end
@@ -165,14 +165,14 @@
         e = GRPC::BadStatus.new(@bs_code, 'NOK')
         expect(@call).to receive(:run_server_bidi).and_raise(e)
         expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
-                                                         {})
+                                                         metadata: {})
         @bidi_streamer.run_server_method(@call, method(:bad_status_alt))
       end
 
       it 'sends status UNKNOWN if other StandardErrors are raised' do
         expect(@call).to receive(:run_server_bidi).and_raise(StandardError)
         expect(@call).to receive(:send_status).once.with(UNKNOWN, @no_reason,
-                                                         false, {})
+                                                         false, metadata: {})
         @bidi_streamer.run_server_method(@call, method(:other_error_alt))
       end
 
@@ -180,7 +180,7 @@
         expect(@call).to receive(:run_server_bidi)
         expect(@call).to receive(:output_metadata).and_return(fake_md)
         expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
-                                                         **fake_md)
+                                                         metadata: fake_md)
         @bidi_streamer.run_server_method(@call, method(:fake_bidistream))
       end
     end
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index 2a42736..943502c 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -99,7 +99,7 @@
   end
 
   def an_rpc(_req, _call)
-    fail GRPC::BadStatus.new(@code, @details, **@md)
+    fail GRPC::BadStatus.new(@code, @details, @md)
   end
 end
 
@@ -137,24 +137,11 @@
     @noop = proc { |x| x }
 
     @server_queue = GRPC::Core::CompletionQueue.new
-    server_host = '0.0.0.0:0'
-    @server = GRPC::Core::Server.new(@server_queue, nil)
-    server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
-    @host = "localhost:#{server_port}"
-    @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
   end
 
   describe '#new' do
     it 'can be created with just some args' do
-      opts = { a_channel_arg: 'an_arg' }
-      blk = proc do
-        RpcServer.new(**opts)
-      end
-      expect(&blk).not_to raise_error
-    end
-
-    it 'can be created with a default deadline' do
-      opts = { a_channel_arg: 'an_arg', deadline: 5 }
+      opts = { server_args: { a_channel_arg: 'an_arg' } }
       blk = proc do
         RpcServer.new(**opts)
       end
@@ -163,7 +150,7 @@
 
     it 'can be created with a completion queue override' do
       opts = {
-        a_channel_arg: 'an_arg',
+        server_args: { a_channel_arg: 'an_arg' },
         completion_queue_override: @server_queue
       }
       blk = proc do
@@ -175,7 +162,7 @@
     it 'cannot be created with a bad completion queue override' do
       blk = proc do
         opts = {
-          a_channel_arg: 'an_arg',
+          server_args: { a_channel_arg: 'an_arg' },
           completion_queue_override: Object.new
         }
         RpcServer.new(**opts)
@@ -186,38 +173,20 @@
     it 'cannot be created with invalid ServerCredentials' do
       blk = proc do
         opts = {
-          a_channel_arg: 'an_arg',
+          server_args: { a_channel_arg: 'an_arg' },
           creds: Object.new
         }
         RpcServer.new(**opts)
       end
       expect(&blk).to raise_error
     end
-
-    it 'can be created with a server override' do
-      opts = { a_channel_arg: 'an_arg', server_override: @server }
-      blk = proc do
-        RpcServer.new(**opts)
-      end
-      expect(&blk).not_to raise_error
-    end
-
-    it 'cannot be created with a bad server override' do
-      blk = proc do
-        opts = {
-          a_channel_arg: 'an_arg',
-          server_override: Object.new
-        }
-        RpcServer.new(**opts)
-      end
-      expect(&blk).to raise_error
-    end
   end
 
   describe '#stopped?' do
     before(:each) do
-      opts = { a_channel_arg: 'an_arg', poll_period: 1.5 }
+      opts = { server_args: { a_channel_arg: 'an_arg' }, poll_period: 1.5 }
       @srv = RpcServer.new(**opts)
+      @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
     end
 
     it 'starts out false' do
@@ -245,28 +214,30 @@
 
   describe '#running?' do
     it 'starts out false' do
-      opts = { a_channel_arg: 'an_arg', server_override: @server }
+      opts = {
+        server_args: { a_channel_arg: 'an_arg' }
+      }
       r = RpcServer.new(**opts)
       expect(r.running?).to be(false)
     end
 
     it 'is false if run is called with no services registered', server: true do
       opts = {
-        a_channel_arg: 'an_arg',
-        poll_period: 2,
-        server_override: @server
+        server_args: { a_channel_arg: 'an_arg' },
+        poll_period: 2
       }
       r = RpcServer.new(**opts)
+      r.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
       expect { r.run }.to raise_error(RuntimeError)
     end
 
     it 'is true after run is called with a registered service' do
       opts = {
-        a_channel_arg: 'an_arg',
-        poll_period: 2.5,
-        server_override: @server
+        server_args: { a_channel_arg: 'an_arg' },
+        poll_period: 2.5
       }
       r = RpcServer.new(**opts)
+      r.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
       r.handle(EchoService)
       t = Thread.new { r.run }
       r.wait_till_running
@@ -278,8 +249,9 @@
 
   describe '#handle' do
     before(:each) do
-      @opts = { a_channel_arg: 'an_arg', poll_period: 1 }
+      @opts = { server_args: { a_channel_arg: 'an_arg' }, poll_period: 1 }
       @srv = RpcServer.new(**@opts)
+      @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
     end
 
     it 'raises if #run has already been called' do
@@ -322,11 +294,13 @@
     context 'with no connect_metadata' do
       before(:each) do
         server_opts = {
-          server_override: @server,
           completion_queue_override: @server_queue,
           poll_period: 1
         }
         @srv = RpcServer.new(**server_opts)
+        server_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+        @host = "localhost:#{server_port}"
+        @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
       end
 
       it 'should return NOT_FOUND status on unknown methods', server: true do
@@ -383,7 +357,8 @@
         @srv.wait_till_running
         req = EchoMsg.new
         stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
-        expect(stub.an_rpc(req, k1: 'v1', k2: 'v2')).to be_a(EchoMsg)
+        expect(stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }))
+          .to be_a(EchoMsg)
         wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
         check_md(wanted_md, service.received_md)
         @srv.stop
@@ -397,8 +372,11 @@
         @srv.wait_till_running
         req = EchoMsg.new
         stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
-        timeout = service.delay + 1.0 # wait for long enough
-        resp = stub.an_rpc(req, timeout: timeout, k1: 'v1', k2: 'v2')
+        timeout = service.delay + 1.0
+        deadline = GRPC::Core::TimeConsts.from_relative_time(timeout)
+        resp = stub.an_rpc(req,
+                           deadline: deadline,
+                           metadata: { k1: 'v1', k2: 'v2' })
         expect(resp).to be_a(EchoMsg)
         wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
         check_md(wanted_md, service.received_md)
@@ -413,7 +391,7 @@
         @srv.wait_till_running
         req = EchoMsg.new
         stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
-        op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
+        op = stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }, return_op: true)
         Thread.new do  # cancel the call
           sleep 0.1
           op.cancel
@@ -443,8 +421,7 @@
 
       it 'should return RESOURCE_EXHAUSTED on too many jobs', server: true do
         opts = {
-          a_channel_arg: 'an_arg',
-          server_override: @server,
+          server_args: { a_channel_arg: 'an_arg' },
           completion_queue_override: @server_queue,
           pool_size: 1,
           poll_period: 1,
@@ -452,6 +429,8 @@
         }
         alt_srv = RpcServer.new(**opts)
         alt_srv.handle(SlowService)
+        alt_port = alt_srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+        alt_host = "0.0.0.0:#{alt_port}"
         t = Thread.new { alt_srv.run }
         alt_srv.wait_till_running
         req = EchoMsg.new
@@ -460,7 +439,7 @@
         one_failed_as_unavailable = false
         n.times do
           threads << Thread.new do
-            stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
+            stub = SlowStub.new(alt_host, :this_channel_is_insecure)
             begin
               stub.an_rpc(req)
             rescue GRPC::BadStatus => e
@@ -487,12 +466,13 @@
       end
       before(:each) do
         server_opts = {
-          server_override: @server,
           completion_queue_override: @server_queue,
           poll_period: 1,
           connect_md_proc: test_md_proc
         }
         @srv = RpcServer.new(**server_opts)
+        alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+        @alt_host = "0.0.0.0:#{alt_port}"
       end
 
       it 'should send connect metadata to the client', server: true do
@@ -501,8 +481,8 @@
         t = Thread.new { @srv.run }
         @srv.wait_till_running
         req = EchoMsg.new
-        stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
-        op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
+        stub = EchoStub.new(@alt_host, :this_channel_is_insecure)
+        op = stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }, return_op: true)
         expect(op.metadata).to be nil
         expect(op.execute).to be_a(EchoMsg)
         wanted_md = {
@@ -522,11 +502,12 @@
     context 'with trailing metadata' do
       before(:each) do
         server_opts = {
-          server_override: @server,
           completion_queue_override: @server_queue,
           poll_period: 1
         }
         @srv = RpcServer.new(**server_opts)
+        alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+        @alt_host = "0.0.0.0:#{alt_port}"
       end
 
       it 'should be added to BadStatus when requests fail', server: true do
@@ -535,7 +516,7 @@
         t = Thread.new { @srv.run }
         @srv.wait_till_running
         req = EchoMsg.new
-        stub = FailingStub.new(@host, :this_channel_is_insecure, **client_opts)
+        stub = FailingStub.new(@alt_host, :this_channel_is_insecure)
         blk = proc { stub.an_rpc(req) }
 
         # confirm it raise the expected error
@@ -560,8 +541,8 @@
         t = Thread.new { @srv.run }
         @srv.wait_till_running
         req = EchoMsg.new
-        stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
-        op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
+        stub = EchoStub.new(@alt_host, :this_channel_is_insecure)
+        op = stub.an_rpc(req, return_op: true, metadata: { k1: 'v1', k2: 'v2' })
         expect(op.metadata).to be nil
         expect(op.execute).to be_a(EchoMsg)
         expect(op.metadata).to eq(wanted_trailers)
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index 5523347..f3d121a 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -170,17 +170,15 @@
     before(:each) do
       @server_queue = GRPC::Core::CompletionQueue.new
       server_host = '0.0.0.0:0'
-      @server = GRPC::Core::Server.new(@server_queue, nil)
-      server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
-      @host = "localhost:#{server_port}"
-      @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
       @client_opts = { channel_override: @ch }
       server_opts = {
-        server_override: @server,
         completion_queue_override: @server_queue,
         poll_period: 1
       }
       @srv = RpcServer.new(**server_opts)
+      server_port = @srv.add_http2_port(server_host, :this_port_is_insecure)
+      @host = "localhost:#{server_port}"
+      @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
     end
 
     after(:each) do
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 0d5f0ec..f84b5f6 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -1207,7 +1207,7 @@
   $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_zookeeper.pc:
   	$(E) "[MAKE]    Generating $@"
   	$(Q) mkdir -p $(@D)
-  	$(Q) echo -e "$(GRPC_ZOOKEEPER_PC_FILE)" >$@
+  	$(Q) echo "$(GRPC_ZOOKEEPER_PC_FILE)" | tr , '\n' >$@
 
   $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc:
   	$(E) "[MAKE]    Generating $@"
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 63132da..85f9a7d 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -12,7 +12,7 @@
     <email>grpc-packages@google.com</email>
     <active>yes</active>
    </lead>
-   <date>2016-04-19</date>
+   <date>2016-05-19</date>
    <time>16:06:07</time>
    <version>
     <release>${settings.php_version.php()}</release>
@@ -24,7 +24,7 @@
    </stability>
    <license>BSD</license>
    <notes>
-  - destroy grpc_byte_buffer after startBatch #6096
+  - TBD
    </notes>
    <contents>
     <dir baseinstalldir="/" name="/">
@@ -172,8 +172,8 @@
     </release>
     <release>
      <version>
-      <release>${settings.php_version.php()}</release>
-      <api>${settings.php_version.php()}</api>
+      <release>0.14.0</release>
+      <api>0.14.0</api>
      </version>
      <stability>
       <release>beta</release>
@@ -185,5 +185,35 @@
   - destroy grpc_byte_buffer after startBatch #6096
      </notes>
     </release>
+    <release>
+     <version>
+      <release>0.14.2</release>
+      <api>0.14.2</api>
+     </version>
+     <stability>
+      <release>beta</release>
+      <api>beta</api>
+     </stability>
+     <date>2016-05-18</date>
+     <license>BSD</license>
+     <notes>
+  - Updated functions with TSRM macros for ZTS support #6607
+     </notes>
+    </release>
+    <release>
+     <version>
+      <release>${settings.php_version.php()}</release>
+      <api>${settings.php_version.php()}</api>
+     </version>
+     <stability>
+      <release>beta</release>
+      <api>beta</api>
+     </stability>
+     <date>2016-05-19</date>
+     <license>BSD</license>
+     <notes>
+  - TBD
+     </notes>
+    </release>
    </changelog>
   </package>
diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages.bat.template
index 93a3531..122435a 100644
--- a/templates/src/csharp/build_packages.bat.template
+++ b/templates/src/csharp/build_packages.bat.template
@@ -33,7 +33,7 @@
   
   @rem Current package versions
   set VERSION=${settings.csharp_version}
-  set PROTOBUF_VERSION=3.0.0-beta2
+  set PROTOBUF_VERSION=3.0.0-beta3
   
   @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
   set VERSION_WITH_BETA=%VERSION%-beta
diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template
index 8e2140e..9987e35 100644
--- a/templates/tools/dockerfile/test/sanity/Dockerfile.template
+++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template
@@ -29,7 +29,7 @@
   # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
-  FROM debian:jessie
+  FROM ubuntu:15.10
   
   <%include file="../../apt_get_basic.include"/>
   #========================
@@ -46,10 +46,8 @@
   
   #======================================
   # More sanity test dependencies (bazel)
-  RUN echo "deb http://httpredir.debian.org/debian jessie-backports main" > \
-    /etc/apt/sources.list.d/backports.list
-  RUN apt-get update
-  RUN apt-get -t jessie-backports install -y openjdk-8-jdk
+  RUN apt-get install -y openjdk-8-jdk
+  # TOOD(jtattermusch): pin the bazel version
   RUN git clone https://github.com/bazelbuild/bazel.git /bazel
   RUN cd /bazel && ./compile.sh
   RUN ln -s /bazel/output/bazel /bin/
@@ -58,7 +56,6 @@
   # Docker "inception"
   # Note this is quite the ugly hack.
   # This makes sure that the docker binary we inject has its dependencies.
-  RUN apt-get install libsystemd-journal0
   RUN curl https://get.docker.com/ | sh
   RUN apt-get remove --purge -y docker-engine
   
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index e582068..f753b6f 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -70,7 +70,7 @@
 static void server_setup_transport(void *ts, grpc_transport *transport) {
   thd_args *a = ts;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_server_setup_transport(&exec_ctx, a->server, transport,
+  grpc_server_setup_transport(&exec_ctx, a->server, transport, NULL,
                               grpc_server_get_channel_args(a->server));
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c
index c1b8452..5390c4a 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -41,7 +41,7 @@
 
 #include "src/core/ext/client_config/initial_connect_string.h"
 #include "src/core/lib/iomgr/sockaddr.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
 #include "src/core/lib/support/string.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -69,6 +69,8 @@
   GPR_ASSERT(success);
   gpr_slice_buffer_move_into(&state.temp_incoming_buffer,
                              &state.incoming_buffer);
+  gpr_log(GPR_DEBUG, "got %d bytes, magic is %d bytes",
+          state.incoming_buffer.length, strlen(magic_connect_string));
   if (state.incoming_buffer.length > strlen(magic_connect_string)) {
     gpr_atm_rel_store(&state.done_atm, 1);
     grpc_endpoint_shutdown(exec_ctx, state.tcp);
@@ -80,6 +82,7 @@
 }
 
 static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
+                       grpc_pollset *accepting_pollset,
                        grpc_tcp_server_acceptor *acceptor) {
   test_tcp_server *server = arg;
   grpc_closure_init(&on_read, handle_read, NULL);
@@ -117,7 +120,6 @@
 }
 
 static void start_rpc(int use_creds, int target_port) {
-  gpr_atm_rel_store(&state.done_atm, 0);
   state.cq = grpc_completion_queue_create(NULL);
   if (use_creds) {
     state.creds = grpc_fake_transport_security_credentials_create();
@@ -166,8 +168,15 @@
 static void actually_poll_server(void *arg) {
   poll_args *pa = arg;
   gpr_timespec deadline = n_sec_deadline(10);
-  while (gpr_atm_acq_load(&state.done_atm) == 0 &&
-         gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
+  while (true) {
+    bool done = gpr_atm_acq_load(&state.done_atm) != 0;
+    gpr_timespec time_left =
+        gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
+    gpr_log(GPR_DEBUG, "done=%d, time_left=%d.%09d", done, time_left.tv_sec,
+            time_left.tv_nsec);
+    if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
+      break;
+    }
     test_tcp_server_poll(pa->server, 1);
   }
   gpr_event_set(pa->signal_when_done, (void *)1);
@@ -176,6 +185,7 @@
 
 static void poll_server_until_read_done(test_tcp_server *server,
                                         gpr_event *signal_when_done) {
+  gpr_atm_rel_store(&state.done_atm, 0);
   gpr_thd_id id;
   poll_args *pa = gpr_malloc(sizeof(*pa));
   pa->server = server;
diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c
index 246619b..44408b2 100644
--- a/test/core/end2end/fixtures/h2_fakesec.c
+++ b/test/core/end2end/fixtures/h2_fakesec.c
@@ -40,7 +40,7 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 550ff33..fc56998 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/iomgr.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 87533a9..6b0769b 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -50,6 +50,7 @@
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -60,7 +61,9 @@
 static void server_setup_transport(void *ts, grpc_transport *transport) {
   grpc_end2end_test_fixture *f = ts;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_server_setup_transport(&exec_ctx, f->server, transport,
+  grpc_endpoint_pair *sfd = f->fixture_data;
+  grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq));
+  grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL,
                               grpc_server_get_channel_args(f->server));
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c
index f28147c..7be88f8 100644
--- a/test/core/end2end/fixtures/h2_sockpair.c
+++ b/test/core/end2end/fixtures/h2_sockpair.c
@@ -49,6 +49,7 @@
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -59,7 +60,9 @@
 static void server_setup_transport(void *ts, grpc_transport *transport) {
   grpc_end2end_test_fixture *f = ts;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_server_setup_transport(&exec_ctx, f->server, transport,
+  grpc_endpoint_pair *sfd = f->fixture_data;
+  grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq));
+  grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL,
                               grpc_server_get_channel_args(f->server));
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index 302b16b..166654b 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -49,6 +49,7 @@
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -59,7 +60,9 @@
 static void server_setup_transport(void *ts, grpc_transport *transport) {
   grpc_end2end_test_fixture *f = ts;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_server_setup_transport(&exec_ctx, f->server, transport,
+  grpc_endpoint_pair *sfd = f->fixture_data;
+  grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq));
+  grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL,
                               grpc_server_get_channel_args(f->server));
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c
index 69f7616..eb28623 100644
--- a/test/core/end2end/fixtures/h2_ssl.c
+++ b/test/core/end2end/fixtures/h2_ssl.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
index f4dea2c..0fa5251 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c
index 151a86c..238e6bc 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.c
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index f6e01ec..7f10649 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -282,6 +282,8 @@
     err = grpc_call_start_batch(pc->c2p, &op, 1,
                                 new_closure(on_c2p_sent_message, pc), NULL);
     GPR_ASSERT(err == GRPC_CALL_OK);
+  } else {
+    grpc_byte_buffer_destroy(pc->p2s_msg);
   }
   unrefpc(pc, "on_p2s_recv_msg");
 }
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index b133a94..e6cd88a 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -252,7 +252,7 @@
 
     grpc_transport *transport =
         grpc_create_chttp2_transport(exec_ctx, NULL, server, 0);
-    grpc_server_setup_transport(exec_ctx, g_server, transport, NULL);
+    grpc_server_setup_transport(exec_ctx, g_server, transport, NULL, NULL);
     grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
 
     grpc_exec_ctx_enqueue(exec_ctx, fc->closure, false, NULL);
@@ -340,6 +340,8 @@
 
 typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type;
 
+#define DONE_FLAG_CALL_CLOSED ((uint64_t)(1 << 0))
+
 typedef struct call_state {
   call_state_type type;
   grpc_call *call;
@@ -352,6 +354,10 @@
   int cancelled;
   int pending_ops;
   grpc_call_details call_details;
+  grpc_byte_buffer *send_message;
+  // starts at 0, individual flags from DONE_FLAG_xxx are set
+  // as different operations are completed
+  uint64_t done_flags;
 
   // array of pointers to free later
   size_t num_to_free;
@@ -418,15 +424,19 @@
 static void read_metadata(input_stream *inp, size_t *count,
                           grpc_metadata **metadata, call_state *cs) {
   *count = next_byte(inp);
-  *metadata = gpr_malloc(*count * sizeof(**metadata));
-  memset(*metadata, 0, *count * sizeof(**metadata));
-  for (size_t i = 0; i < *count; i++) {
-    (*metadata)[i].key = read_string(inp);
-    read_buffer(inp, (char **)&(*metadata)[i].value,
-                &(*metadata)[i].value_length);
-    (*metadata)[i].flags = read_uint32(inp);
-    add_to_free(cs, (void *)(*metadata)[i].key);
-    add_to_free(cs, (void *)(*metadata)[i].value);
+  if (*count) {
+    *metadata = gpr_malloc(*count * sizeof(**metadata));
+    memset(*metadata, 0, *count * sizeof(**metadata));
+    for (size_t i = 0; i < *count; i++) {
+      (*metadata)[i].key = read_string(inp);
+      read_buffer(inp, (char **)&(*metadata)[i].value,
+                  &(*metadata)[i].value_length);
+      (*metadata)[i].flags = read_uint32(inp);
+      add_to_free(cs, (void *)(*metadata)[i].key);
+      add_to_free(cs, (void *)(*metadata)[i].value);
+    }
+  } else {
+    *metadata = gpr_malloc(1);
   }
   add_to_free(cs, *metadata);
 }
@@ -449,10 +459,41 @@
   }
 }
 
-static void finished_batch(void *csp, bool success) {
-  call_state *cs = csp;
-  --cs->pending_ops;
-  maybe_delete_call_state(cs);
+typedef struct {
+  call_state *cs;
+  uint8_t has_ops;
+} batch_info;
+
+static void finished_batch(void *p, bool success) {
+  batch_info *bi = p;
+  --bi->cs->pending_ops;
+  if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE)) &&
+      (bi->cs->done_flags & DONE_FLAG_CALL_CLOSED)) {
+    GPR_ASSERT(bi->cs->recv_message == NULL);
+  }
+  if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE) &&
+       bi->cs->recv_message != NULL)) {
+    grpc_byte_buffer_destroy(bi->cs->recv_message);
+    bi->cs->recv_message = NULL;
+  }
+  if ((bi->has_ops & (1u << GRPC_OP_SEND_MESSAGE))) {
+    grpc_byte_buffer_destroy(bi->cs->send_message);
+    bi->cs->send_message = NULL;
+  }
+  if ((bi->has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) ||
+      (bi->has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) {
+    bi->cs->done_flags |= DONE_FLAG_CALL_CLOSED;
+  }
+  maybe_delete_call_state(bi->cs);
+  gpr_free(bi);
+}
+
+static validator *make_finished_batch_validator(call_state *cs,
+                                                uint8_t has_ops) {
+  batch_info *bi = gpr_malloc(sizeof(*bi));
+  bi->cs = cs;
+  bi->has_ops = has_ops;
+  return create_validator(finished_batch, bi);
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
@@ -579,6 +620,7 @@
         } else {
           end(&inp);
         }
+        break;
       }
       // begin server shutdown
       case 5: {
@@ -700,6 +742,7 @@
         bool ok = true;
         size_t i;
         grpc_op *op;
+        uint8_t has_ops = 0;
         for (i = 0; i < num_ops; i++) {
           op = &ops[i];
           switch (next_byte(&inp)) {
@@ -710,19 +753,28 @@
               break;
             case GRPC_OP_SEND_INITIAL_METADATA:
               op->op = GRPC_OP_SEND_INITIAL_METADATA;
+              has_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA;
               read_metadata(&inp, &op->data.send_initial_metadata.count,
                             &op->data.send_initial_metadata.metadata,
                             g_active_call);
               break;
             case GRPC_OP_SEND_MESSAGE:
               op->op = GRPC_OP_SEND_MESSAGE;
-              op->data.send_message = read_message(&inp);
+              if (g_active_call->send_message != NULL) {
+                ok = false;
+              } else {
+                has_ops |= 1 << GRPC_OP_SEND_MESSAGE;
+                g_active_call->send_message = op->data.send_message =
+                    read_message(&inp);
+              }
               break;
             case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
               op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+              has_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT;
               break;
             case GRPC_OP_SEND_STATUS_FROM_SERVER:
               op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+              has_ops |= 1 << GRPC_OP_SEND_STATUS_FROM_SERVER;
               read_metadata(
                   &inp,
                   &op->data.send_status_from_server.trailing_metadata_count,
@@ -734,11 +786,13 @@
               break;
             case GRPC_OP_RECV_INITIAL_METADATA:
               op->op = GRPC_OP_RECV_INITIAL_METADATA;
+              has_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA;
               op->data.recv_initial_metadata =
                   &g_active_call->recv_initial_metadata;
               break;
             case GRPC_OP_RECV_MESSAGE:
               op->op = GRPC_OP_RECV_MESSAGE;
+              has_ops |= 1 << GRPC_OP_RECV_MESSAGE;
               op->data.recv_message = &g_active_call->recv_message;
               break;
             case GRPC_OP_RECV_STATUS_ON_CLIENT:
@@ -753,6 +807,7 @@
               break;
             case GRPC_OP_RECV_CLOSE_ON_SERVER:
               op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+              has_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER;
               op->data.recv_close_on_server.cancelled =
                   &g_active_call->cancelled;
               break;
@@ -761,7 +816,7 @@
           op->flags = read_uint32(&inp);
         }
         if (ok) {
-          validator *v = create_validator(finished_batch, g_active_call);
+          validator *v = make_finished_batch_validator(g_active_call, has_ops);
           g_active_call->pending_ops++;
           grpc_call_error error =
               grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL);
@@ -772,17 +827,18 @@
         } else {
           end(&inp);
         }
+        if (!ok && (has_ops & (1 << GRPC_OP_SEND_MESSAGE))) {
+          grpc_byte_buffer_destroy(g_active_call->send_message);
+          g_active_call->send_message = NULL;
+        }
         for (i = 0; i < num_ops; i++) {
           op = &ops[i];
           switch (op->op) {
-            case GRPC_OP_SEND_INITIAL_METADATA:
-              break;
-            case GRPC_OP_SEND_MESSAGE:
-              grpc_byte_buffer_destroy(op->data.send_message);
-              break;
             case GRPC_OP_SEND_STATUS_FROM_SERVER:
               gpr_free((void *)op->data.send_status_from_server.status_details);
               break;
+            case GRPC_OP_SEND_MESSAGE:
+            case GRPC_OP_SEND_INITIAL_METADATA:
             case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
             case GRPC_OP_RECV_INITIAL_METADATA:
             case GRPC_OP_RECV_MESSAGE:
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/001ea98069c10f808c281da9bbdd84cc05c3bad1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/001ea98069c10f808c281da9bbdd84cc05c3bad1
new file mode 100644
index 0000000..11d72eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/001ea98069c10f808c281da9bbdd84cc05c3bad1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/01f52e31dfffdab89d83acd39925c3dd81baa76f b/test/core/end2end/fuzzers/api_fuzzer_corpus/01f52e31dfffdab89d83acd39925c3dd81baa76f
new file mode 100644
index 0000000..1d2f30d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/01f52e31dfffdab89d83acd39925c3dd81baa76f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/02c3cf8d52fbc43f89b5f516a17cea23b68fc8d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/02c3cf8d52fbc43f89b5f516a17cea23b68fc8d5
new file mode 100644
index 0000000..3e1eee3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/02c3cf8d52fbc43f89b5f516a17cea23b68fc8d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/032744b59cafd3320cc932ad39926a9bc92f589e b/test/core/end2end/fuzzers/api_fuzzer_corpus/032744b59cafd3320cc932ad39926a9bc92f589e
new file mode 100644
index 0000000..18bf828
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/032744b59cafd3320cc932ad39926a9bc92f589e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0385c7b41263419e25a4342fbfc44fbd65eb2ed5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0385c7b41263419e25a4342fbfc44fbd65eb2ed5
new file mode 100644
index 0000000..aac4f3c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0385c7b41263419e25a4342fbfc44fbd65eb2ed5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/04d93c9df413717f71abd091592b5238afb799e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/04d93c9df413717f71abd091592b5238afb799e8
new file mode 100644
index 0000000..10f3d31
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/04d93c9df413717f71abd091592b5238afb799e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/064d50aee4416ccf32f4e4fe7b770b7802265ffe b/test/core/end2end/fuzzers/api_fuzzer_corpus/064d50aee4416ccf32f4e4fe7b770b7802265ffe
new file mode 100644
index 0000000..ce911ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/064d50aee4416ccf32f4e4fe7b770b7802265ffe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/066e7fcb68e83b432c414f63f6de73e5f5099e49 b/test/core/end2end/fuzzers/api_fuzzer_corpus/066e7fcb68e83b432c414f63f6de73e5f5099e49
new file mode 100644
index 0000000..1ea8911
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/066e7fcb68e83b432c414f63f6de73e5f5099e49
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06c714e289673cf982ce2ac0670707a15f2ac5ea b/test/core/end2end/fuzzers/api_fuzzer_corpus/06c714e289673cf982ce2ac0670707a15f2ac5ea
new file mode 100644
index 0000000..f43c3fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06c714e289673cf982ce2ac0670707a15f2ac5ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/071247b8fddda8aa520d9142c89039fbf8bf6cee b/test/core/end2end/fuzzers/api_fuzzer_corpus/071247b8fddda8aa520d9142c89039fbf8bf6cee
new file mode 100644
index 0000000..06505f5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/071247b8fddda8aa520d9142c89039fbf8bf6cee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07cb3b9baca1bbcce2e199e551073ba2fdd4e05c b/test/core/end2end/fuzzers/api_fuzzer_corpus/07cb3b9baca1bbcce2e199e551073ba2fdd4e05c
new file mode 100644
index 0000000..f6320aa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07cb3b9baca1bbcce2e199e551073ba2fdd4e05c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07fa2b6ed650d436f423adcccfcbe63ce6253de0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/07fa2b6ed650d436f423adcccfcbe63ce6253de0
new file mode 100644
index 0000000..a359ef3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07fa2b6ed650d436f423adcccfcbe63ce6253de0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/081e3248dfca2b32837c4738daee3a4698caaf15 b/test/core/end2end/fuzzers/api_fuzzer_corpus/081e3248dfca2b32837c4738daee3a4698caaf15
new file mode 100644
index 0000000..e29f884
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/081e3248dfca2b32837c4738daee3a4698caaf15
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/088bf259e854abd9508d91b23983737f8e9e242c b/test/core/end2end/fuzzers/api_fuzzer_corpus/088bf259e854abd9508d91b23983737f8e9e242c
new file mode 100644
index 0000000..b60cdde
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/088bf259e854abd9508d91b23983737f8e9e242c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde b/test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde
new file mode 100644
index 0000000..57b8f4c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606
new file mode 100644
index 0000000..c6be6e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0af5adf68560b3a7036ad23af62e4f9749eca690 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0af5adf68560b3a7036ad23af62e4f9749eca690
new file mode 100644
index 0000000..9acf287
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0af5adf68560b3a7036ad23af62e4f9749eca690
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0becc6ede499ddc452fd4e6c3c0413a1107a8373 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0becc6ede499ddc452fd4e6c3c0413a1107a8373
new file mode 100644
index 0000000..a942070
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0becc6ede499ddc452fd4e6c3c0413a1107a8373
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0c531e03e56a5cf48bdd531a8c11a19e4a3b0aeb b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c531e03e56a5cf48bdd531a8c11a19e4a3b0aeb
new file mode 100644
index 0000000..3dcd1e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c531e03e56a5cf48bdd531a8c11a19e4a3b0aeb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0c65733bc09e8527347e20f5c876c5b64570d423 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c65733bc09e8527347e20f5c876c5b64570d423
new file mode 100644
index 0000000..1170a8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c65733bc09e8527347e20f5c876c5b64570d423
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0c7b763d22885462527123656fa17af7520fc55d b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c7b763d22885462527123656fa17af7520fc55d
new file mode 100644
index 0000000..0f07f6b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c7b763d22885462527123656fa17af7520fc55d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd
new file mode 100644
index 0000000..d0d56da
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d993b34021ec088f1aa3e5acdd98089b4104b07 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d993b34021ec088f1aa3e5acdd98089b4104b07
new file mode 100644
index 0000000..ca3a14b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d993b34021ec088f1aa3e5acdd98089b4104b07
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0def53b5575cc6ab2fbbd17e2bc6a24de9656f84 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0def53b5575cc6ab2fbbd17e2bc6a24de9656f84
new file mode 100644
index 0000000..30addfc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0def53b5575cc6ab2fbbd17e2bc6a24de9656f84
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2ddbe92c08eb9ad3cbee1d0db2264baaca12df b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2ddbe92c08eb9ad3cbee1d0db2264baaca12df
new file mode 100644
index 0000000..3fc360d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e2ddbe92c08eb9ad3cbee1d0db2264baaca12df
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0ea509d249ae28faba8980aacb972c7ea28d3fd5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ea509d249ae28faba8980aacb972c7ea28d3fd5
new file mode 100644
index 0000000..4c213b1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ea509d249ae28faba8980aacb972c7ea28d3fd5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0f16eeeecdebcb59022bda5a0972d1b3429648fd b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f16eeeecdebcb59022bda5a0972d1b3429648fd
new file mode 100644
index 0000000..0116d00
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f16eeeecdebcb59022bda5a0972d1b3429648fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0f81830560dbb9c6d3889b5d581b918c6cade65f b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f81830560dbb9c6d3889b5d581b918c6cade65f
new file mode 100644
index 0000000..789a994
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f81830560dbb9c6d3889b5d581b918c6cade65f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/105d9784648fe2d6c22fbefa69c9a26fff1c6481 b/test/core/end2end/fuzzers/api_fuzzer_corpus/105d9784648fe2d6c22fbefa69c9a26fff1c6481
new file mode 100644
index 0000000..a6aa6cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/105d9784648fe2d6c22fbefa69c9a26fff1c6481
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/11153bfeee3cdede86a52151dbb939c3ffee48ed b/test/core/end2end/fuzzers/api_fuzzer_corpus/11153bfeee3cdede86a52151dbb939c3ffee48ed
new file mode 100644
index 0000000..5885a28
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/11153bfeee3cdede86a52151dbb939c3ffee48ed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/113c1d1bac15d550124f1ffb9012c32755adf27f b/test/core/end2end/fuzzers/api_fuzzer_corpus/113c1d1bac15d550124f1ffb9012c32755adf27f
new file mode 100644
index 0000000..d7eba10
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/113c1d1bac15d550124f1ffb9012c32755adf27f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/11759723c597e6806f8873e5062d31516cdb97ea b/test/core/end2end/fuzzers/api_fuzzer_corpus/11759723c597e6806f8873e5062d31516cdb97ea
new file mode 100644
index 0000000..34812d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/11759723c597e6806f8873e5062d31516cdb97ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12abf5dcf2aba770f7b94ce5d96d7a8565a9aa19 b/test/core/end2end/fuzzers/api_fuzzer_corpus/12abf5dcf2aba770f7b94ce5d96d7a8565a9aa19
new file mode 100644
index 0000000..494f031
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12abf5dcf2aba770f7b94ce5d96d7a8565a9aa19
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12b904b97ed234fa45073b4e346ebe3211558528 b/test/core/end2end/fuzzers/api_fuzzer_corpus/12b904b97ed234fa45073b4e346ebe3211558528
new file mode 100644
index 0000000..482fd74
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12b904b97ed234fa45073b4e346ebe3211558528
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12c00ed8945bdae03f03142cb964a47ea0c5786e b/test/core/end2end/fuzzers/api_fuzzer_corpus/12c00ed8945bdae03f03142cb964a47ea0c5786e
new file mode 100644
index 0000000..abc3d13
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12c00ed8945bdae03f03142cb964a47ea0c5786e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/12f977ee18a7499d18a503a47e71b4f241052640 b/test/core/end2end/fuzzers/api_fuzzer_corpus/12f977ee18a7499d18a503a47e71b4f241052640
new file mode 100644
index 0000000..ad424b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/12f977ee18a7499d18a503a47e71b4f241052640
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/145acf7c03a0bc6c4a40d710ba5813b9f28efe2a b/test/core/end2end/fuzzers/api_fuzzer_corpus/145acf7c03a0bc6c4a40d710ba5813b9f28efe2a
new file mode 100644
index 0000000..2e55e9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/145acf7c03a0bc6c4a40d710ba5813b9f28efe2a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/14ccbe1d9d7302d642e51ede3d4d846e85310fc2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/14ccbe1d9d7302d642e51ede3d4d846e85310fc2
new file mode 100644
index 0000000..4940dc4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/14ccbe1d9d7302d642e51ede3d4d846e85310fc2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1586adc8c21b5796ba52203379faeb5f251f5c1d b/test/core/end2end/fuzzers/api_fuzzer_corpus/1586adc8c21b5796ba52203379faeb5f251f5c1d
new file mode 100644
index 0000000..13577d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1586adc8c21b5796ba52203379faeb5f251f5c1d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1608a688768bdecdb205a455401ce5d9a1424a22 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1608a688768bdecdb205a455401ce5d9a1424a22
new file mode 100644
index 0000000..a7f9e46
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1608a688768bdecdb205a455401ce5d9a1424a22
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/162b4ec7cf39df091898e01057b2fa39605b34bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/162b4ec7cf39df091898e01057b2fa39605b34bb
new file mode 100644
index 0000000..9eb2a6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/162b4ec7cf39df091898e01057b2fa39605b34bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/16858f1f9db0e248a15ce09d9848612de1f4bba6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/16858f1f9db0e248a15ce09d9848612de1f4bba6
new file mode 100644
index 0000000..de7a582
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/16858f1f9db0e248a15ce09d9848612de1f4bba6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/16e681f1867a1ac5612e1a88fddaed0bcb4521e7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/16e681f1867a1ac5612e1a88fddaed0bcb4521e7
new file mode 100644
index 0000000..ca73765
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/16e681f1867a1ac5612e1a88fddaed0bcb4521e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/16ebac3f7cea2b46f660ec6a5ef3401c3e17a2e9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/16ebac3f7cea2b46f660ec6a5ef3401c3e17a2e9
new file mode 100644
index 0000000..417e588
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/16ebac3f7cea2b46f660ec6a5ef3401c3e17a2e9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17ec0503991dc248d2b188edfa3d28573a1c2154 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17ec0503991dc248d2b188edfa3d28573a1c2154
new file mode 100644
index 0000000..6728e2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17ec0503991dc248d2b188edfa3d28573a1c2154
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17fb35db0b73c331a66120dbc491300b2d1665e0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17fb35db0b73c331a66120dbc491300b2d1665e0
new file mode 100644
index 0000000..af0fe1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17fb35db0b73c331a66120dbc491300b2d1665e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/190c4ca0cf29c99bc987d2792c7f62e1007c0245 b/test/core/end2end/fuzzers/api_fuzzer_corpus/190c4ca0cf29c99bc987d2792c7f62e1007c0245
new file mode 100644
index 0000000..fbc532d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/190c4ca0cf29c99bc987d2792c7f62e1007c0245
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1949f4a75f7d501d5279a01f58a444640379bd78 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1949f4a75f7d501d5279a01f58a444640379bd78
new file mode 100644
index 0000000..8a39c9d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1949f4a75f7d501d5279a01f58a444640379bd78
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1972f535ae202777efdd15a09138efc37e07ac01 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1972f535ae202777efdd15a09138efc37e07ac01
new file mode 100644
index 0000000..5c66b0a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1972f535ae202777efdd15a09138efc37e07ac01
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/198e691a9dabd23ed5c156f3a6e2c06a4379c15b b/test/core/end2end/fuzzers/api_fuzzer_corpus/198e691a9dabd23ed5c156f3a6e2c06a4379c15b
new file mode 100644
index 0000000..29be724
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/198e691a9dabd23ed5c156f3a6e2c06a4379c15b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1a16a4b32cb0cb3a759ec20edf332cdfc5d1717e b/test/core/end2end/fuzzers/api_fuzzer_corpus/1a16a4b32cb0cb3a759ec20edf332cdfc5d1717e
new file mode 100644
index 0000000..ec2f8fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1a16a4b32cb0cb3a759ec20edf332cdfc5d1717e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1af0744fe0ccad11d6df023803ab699e1464c8da b/test/core/end2end/fuzzers/api_fuzzer_corpus/1af0744fe0ccad11d6df023803ab699e1464c8da
new file mode 100644
index 0000000..b84ca71
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1af0744fe0ccad11d6df023803ab699e1464c8da
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b6d8326532cea974655dc86657d8e3b9ba021de b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b6d8326532cea974655dc86657d8e3b9ba021de
new file mode 100644
index 0000000..461677d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b6d8326532cea974655dc86657d8e3b9ba021de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b78d906803b539ea9f135e41b58257365948855 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b78d906803b539ea9f135e41b58257365948855
new file mode 100644
index 0000000..ac120a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b78d906803b539ea9f135e41b58257365948855
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1ba0190ef2cde93332f850753a05b89ae5f39f1f b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ba0190ef2cde93332f850753a05b89ae5f39f1f
new file mode 100644
index 0000000..373e44f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ba0190ef2cde93332f850753a05b89ae5f39f1f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c24396c21f2c6aa2ad9b9a14877b7edf0ce61d2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c24396c21f2c6aa2ad9b9a14877b7edf0ce61d2
new file mode 100644
index 0000000..1610b54
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c24396c21f2c6aa2ad9b9a14877b7edf0ce61d2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c86c4f2d173059e5cfe67b446fdfa285743f61f b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c86c4f2d173059e5cfe67b446fdfa285743f61f
new file mode 100644
index 0000000..3fc1394
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c86c4f2d173059e5cfe67b446fdfa285743f61f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1cbbae18babaa20229b42b4633ef812bd3b40ad4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cbbae18babaa20229b42b4633ef812bd3b40ad4
new file mode 100644
index 0000000..21cc2e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cbbae18babaa20229b42b4633ef812bd3b40ad4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7
new file mode 100644
index 0000000..35ee3b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d55650c5bc30ea68168a9287820e25d2d53ab4c b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d55650c5bc30ea68168a9287820e25d2d53ab4c
new file mode 100644
index 0000000..0422004
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d55650c5bc30ea68168a9287820e25d2d53ab4c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d795268725d3a08883b05b021a437654aaed908 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d795268725d3a08883b05b021a437654aaed908
new file mode 100644
index 0000000..a852bac
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d795268725d3a08883b05b021a437654aaed908
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d7bd5961f6963c65054fb9a24d913601f37bf3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d7bd5961f6963c65054fb9a24d913601f37bf3d
new file mode 100644
index 0000000..932ef74
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d7bd5961f6963c65054fb9a24d913601f37bf3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1eefda69c1787cc55a8bd43774ca13563e0972bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/1eefda69c1787cc55a8bd43774ca13563e0972bc
new file mode 100644
index 0000000..92e91dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1eefda69c1787cc55a8bd43774ca13563e0972bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1f4d0adab39a988792cca201626c28293e247226 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f4d0adab39a988792cca201626c28293e247226
new file mode 100644
index 0000000..b50ddd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f4d0adab39a988792cca201626c28293e247226
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1f7847ed44c5acbc52c5d16b0222b44067076478 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f7847ed44c5acbc52c5d16b0222b44067076478
new file mode 100644
index 0000000..c787060
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f7847ed44c5acbc52c5d16b0222b44067076478
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/200521ca3891bfed841ca8c22691196a1a03ccd3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/200521ca3891bfed841ca8c22691196a1a03ccd3
new file mode 100644
index 0000000..cf69ac8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/200521ca3891bfed841ca8c22691196a1a03ccd3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/205dd562c7202d4231b232a6804889e77eba5292 b/test/core/end2end/fuzzers/api_fuzzer_corpus/205dd562c7202d4231b232a6804889e77eba5292
new file mode 100644
index 0000000..21b314d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/205dd562c7202d4231b232a6804889e77eba5292
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2193a1e20caee37676d08c88154a462acf120fb0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2193a1e20caee37676d08c88154a462acf120fb0
new file mode 100644
index 0000000..e3f46b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2193a1e20caee37676d08c88154a462acf120fb0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/21da45db854aeae9bef8576d6cb5859c0cf7a34c b/test/core/end2end/fuzzers/api_fuzzer_corpus/21da45db854aeae9bef8576d6cb5859c0cf7a34c
new file mode 100644
index 0000000..1c7966c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/21da45db854aeae9bef8576d6cb5859c0cf7a34c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/226b0315f87b08521c9a2d3e2b50c01ec421be14 b/test/core/end2end/fuzzers/api_fuzzer_corpus/226b0315f87b08521c9a2d3e2b50c01ec421be14
new file mode 100644
index 0000000..14b54da
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/226b0315f87b08521c9a2d3e2b50c01ec421be14
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/22c9ed2979d9963bce6500997f1e0433988e7e37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/22c9ed2979d9963bce6500997f1e0433988e7e37
new file mode 100644
index 0000000..76f10b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/22c9ed2979d9963bce6500997f1e0433988e7e37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/247d0d09deeeb76422cd1d06305a63378a498656 b/test/core/end2end/fuzzers/api_fuzzer_corpus/247d0d09deeeb76422cd1d06305a63378a498656
new file mode 100644
index 0000000..4dac3e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/247d0d09deeeb76422cd1d06305a63378a498656
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/24fbdfa73f26686633871ddad9698d7059db488f b/test/core/end2end/fuzzers/api_fuzzer_corpus/24fbdfa73f26686633871ddad9698d7059db488f
new file mode 100644
index 0000000..6418261
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/24fbdfa73f26686633871ddad9698d7059db488f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2535940afe69b3106b7696a486a2617d0d9a7150 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2535940afe69b3106b7696a486a2617d0d9a7150
new file mode 100644
index 0000000..59c07a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2535940afe69b3106b7696a486a2617d0d9a7150
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/25aa74daea95f9fc46a78239bd2e78ccf0fb3ffc b/test/core/end2end/fuzzers/api_fuzzer_corpus/25aa74daea95f9fc46a78239bd2e78ccf0fb3ffc
new file mode 100644
index 0000000..9f02718
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/25aa74daea95f9fc46a78239bd2e78ccf0fb3ffc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/26930c35fbe83e4d165b8b7f218ac8ea231c87dd b/test/core/end2end/fuzzers/api_fuzzer_corpus/26930c35fbe83e4d165b8b7f218ac8ea231c87dd
new file mode 100644
index 0000000..074833e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/26930c35fbe83e4d165b8b7f218ac8ea231c87dd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/26dfa46c2bb2e6af6f52bac6f03a9e4406c6e700 b/test/core/end2end/fuzzers/api_fuzzer_corpus/26dfa46c2bb2e6af6f52bac6f03a9e4406c6e700
new file mode 100644
index 0000000..39212d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/26dfa46c2bb2e6af6f52bac6f03a9e4406c6e700
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/27a8643ba6047e12de1b2a4f7d0994a2c095a6d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/27a8643ba6047e12de1b2a4f7d0994a2c095a6d5
new file mode 100644
index 0000000..2c3a0b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/27a8643ba6047e12de1b2a4f7d0994a2c095a6d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/27f5e317e8a3a1098e786b96175c15d0855c4855 b/test/core/end2end/fuzzers/api_fuzzer_corpus/27f5e317e8a3a1098e786b96175c15d0855c4855
new file mode 100644
index 0000000..736534e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/27f5e317e8a3a1098e786b96175c15d0855c4855
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/285b0b9b11fe506527c880d3a866ba94f8038cdf b/test/core/end2end/fuzzers/api_fuzzer_corpus/285b0b9b11fe506527c880d3a866ba94f8038cdf
new file mode 100644
index 0000000..9f3f0a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/285b0b9b11fe506527c880d3a866ba94f8038cdf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/28851da472cd09123465241e0d59697f563f53a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/28851da472cd09123465241e0d59697f563f53a8
new file mode 100644
index 0000000..8a42c04
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/28851da472cd09123465241e0d59697f563f53a8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/28c56acb0f9b47ead49f34c0d92a661fa04952c2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/28c56acb0f9b47ead49f34c0d92a661fa04952c2
new file mode 100644
index 0000000..fa5c746
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/28c56acb0f9b47ead49f34c0d92a661fa04952c2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2923d9c864597016358f37ce4014c61648b7290a b/test/core/end2end/fuzzers/api_fuzzer_corpus/2923d9c864597016358f37ce4014c61648b7290a
new file mode 100644
index 0000000..0476a93
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2923d9c864597016358f37ce4014c61648b7290a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/29a6d7ab3e7ea8d331358df45e5b0926e768e227 b/test/core/end2end/fuzzers/api_fuzzer_corpus/29a6d7ab3e7ea8d331358df45e5b0926e768e227
new file mode 100644
index 0000000..8792e3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/29a6d7ab3e7ea8d331358df45e5b0926e768e227
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a410e3d783bc93e63206e28f92b6a40e1db09cf b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a410e3d783bc93e63206e28f92b6a40e1db09cf
new file mode 100644
index 0000000..803b4bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a410e3d783bc93e63206e28f92b6a40e1db09cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2b80854b52267dd70b622670e401280387f15dd2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b80854b52267dd70b622670e401280387f15dd2
new file mode 100644
index 0000000..1a8b38b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2b80854b52267dd70b622670e401280387f15dd2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589
new file mode 100644
index 0000000..5659e0c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d7f42d3df4a206d09a9fa3126333a61f5e678ec b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d7f42d3df4a206d09a9fa3126333a61f5e678ec
new file mode 100644
index 0000000..7058beb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d7f42d3df4a206d09a9fa3126333a61f5e678ec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d82b2376d689485814ade91df8f65ee08395a02 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d82b2376d689485814ade91df8f65ee08395a02
new file mode 100644
index 0000000..f7ee1cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d82b2376d689485814ade91df8f65ee08395a02
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2df65610f1c24ad1cf9a5b22614434c96ffc12fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/2df65610f1c24ad1cf9a5b22614434c96ffc12fb
new file mode 100644
index 0000000..3101297
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2df65610f1c24ad1cf9a5b22614434c96ffc12fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2e48a9c8d204975060e81f37c7a46ab501750067 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e48a9c8d204975060e81f37c7a46ab501750067
new file mode 100644
index 0000000..7fddf56
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e48a9c8d204975060e81f37c7a46ab501750067
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2e7441eacf8fcc7043f24b3beba4fcbe3c0c5ea0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e7441eacf8fcc7043f24b3beba4fcbe3c0c5ea0
new file mode 100644
index 0000000..c6a5e1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e7441eacf8fcc7043f24b3beba4fcbe3c0c5ea0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ef149e8fd68e06fcb7ba2fb43a17cc1dcfd989b b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ef149e8fd68e06fcb7ba2fb43a17cc1dcfd989b
new file mode 100644
index 0000000..185c9c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ef149e8fd68e06fcb7ba2fb43a17cc1dcfd989b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2f35914500b09477fe245bc130f86bbd15112ce7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f35914500b09477fe245bc130f86bbd15112ce7
new file mode 100644
index 0000000..d1d5abe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2f35914500b09477fe245bc130f86bbd15112ce7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2fece42b158854855dd42eac3fc7b8f1eb61fb04 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2fece42b158854855dd42eac3fc7b8f1eb61fb04
new file mode 100644
index 0000000..d998323
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2fece42b158854855dd42eac3fc7b8f1eb61fb04
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3017e9f66dacf5a01f8c7d65b8a72d4f68aa6a28 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3017e9f66dacf5a01f8c7d65b8a72d4f68aa6a28
new file mode 100644
index 0000000..90a40e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3017e9f66dacf5a01f8c7d65b8a72d4f68aa6a28
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30948ba77c2e56903a9ad5190cc74e59d42f67fe b/test/core/end2end/fuzzers/api_fuzzer_corpus/30948ba77c2e56903a9ad5190cc74e59d42f67fe
new file mode 100644
index 0000000..eb9d316
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30948ba77c2e56903a9ad5190cc74e59d42f67fe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45 b/test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45
new file mode 100644
index 0000000..9a482a0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30fc581d975cd8384b86be0ae59792a605ca68c6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/30fc581d975cd8384b86be0ae59792a605ca68c6
new file mode 100644
index 0000000..52d3fdb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30fc581d975cd8384b86be0ae59792a605ca68c6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3152365a4d8540623c9fb3a93712d096bf6b34e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3152365a4d8540623c9fb3a93712d096bf6b34e6
new file mode 100644
index 0000000..97cf797
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3152365a4d8540623c9fb3a93712d096bf6b34e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/324b9341bfc56b24a60f0687a52981fcdeaa8733 b/test/core/end2end/fuzzers/api_fuzzer_corpus/324b9341bfc56b24a60f0687a52981fcdeaa8733
new file mode 100644
index 0000000..06be6c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/324b9341bfc56b24a60f0687a52981fcdeaa8733
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/32a6ea045d1288418617e5e0c52ae02c1f6598aa b/test/core/end2end/fuzzers/api_fuzzer_corpus/32a6ea045d1288418617e5e0c52ae02c1f6598aa
new file mode 100644
index 0000000..1bcaa23
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/32a6ea045d1288418617e5e0c52ae02c1f6598aa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3356fa1721a0dec9fedacba8d86e6100a49d5316 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3356fa1721a0dec9fedacba8d86e6100a49d5316
new file mode 100644
index 0000000..f742dc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3356fa1721a0dec9fedacba8d86e6100a49d5316
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33af00c8deb0f0fdfc113f21c3cb5769aa474587 b/test/core/end2end/fuzzers/api_fuzzer_corpus/33af00c8deb0f0fdfc113f21c3cb5769aa474587
new file mode 100644
index 0000000..e717415
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33af00c8deb0f0fdfc113f21c3cb5769aa474587
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33b7cb7d4dcd380b207f1137722fe394de2a0f8e b/test/core/end2end/fuzzers/api_fuzzer_corpus/33b7cb7d4dcd380b207f1137722fe394de2a0f8e
new file mode 100644
index 0000000..b2a16c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33b7cb7d4dcd380b207f1137722fe394de2a0f8e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33ff864434b4f0c0e08c00ec2442cb521e9f79ed b/test/core/end2end/fuzzers/api_fuzzer_corpus/33ff864434b4f0c0e08c00ec2442cb521e9f79ed
new file mode 100644
index 0000000..c609864
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33ff864434b4f0c0e08c00ec2442cb521e9f79ed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/34aca5e37920615e8c141ed1fe4e419ae2e4df65 b/test/core/end2end/fuzzers/api_fuzzer_corpus/34aca5e37920615e8c141ed1fe4e419ae2e4df65
new file mode 100644
index 0000000..e70d70e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/34aca5e37920615e8c141ed1fe4e419ae2e4df65
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/35ba1a4df4d362ea98e9386269bfbb95c5ed4874 b/test/core/end2end/fuzzers/api_fuzzer_corpus/35ba1a4df4d362ea98e9386269bfbb95c5ed4874
new file mode 100644
index 0000000..82db6b0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/35ba1a4df4d362ea98e9386269bfbb95c5ed4874
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3662f5312562bbe4503018a820692962e7dd66c8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3662f5312562bbe4503018a820692962e7dd66c8
new file mode 100644
index 0000000..81692d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3662f5312562bbe4503018a820692962e7dd66c8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/37309bbfb4f0d78e6138b13a4e5da5944c95b97d b/test/core/end2end/fuzzers/api_fuzzer_corpus/37309bbfb4f0d78e6138b13a4e5da5944c95b97d
new file mode 100644
index 0000000..18d50cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/37309bbfb4f0d78e6138b13a4e5da5944c95b97d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/37bc0646132afe8c79cda5e76de150a473fc0680 b/test/core/end2end/fuzzers/api_fuzzer_corpus/37bc0646132afe8c79cda5e76de150a473fc0680
new file mode 100644
index 0000000..d4a1f95
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/37bc0646132afe8c79cda5e76de150a473fc0680
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/385626d51cd29e1b32befeaecde5df7248270754 b/test/core/end2end/fuzzers/api_fuzzer_corpus/385626d51cd29e1b32befeaecde5df7248270754
new file mode 100644
index 0000000..c300fae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/385626d51cd29e1b32befeaecde5df7248270754
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea b/test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea
new file mode 100644
index 0000000..5c7ff7b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/391ef74273ae5e1cd8a2342c5370fde5df1a7140 b/test/core/end2end/fuzzers/api_fuzzer_corpus/391ef74273ae5e1cd8a2342c5370fde5df1a7140
new file mode 100644
index 0000000..dbdef3f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/391ef74273ae5e1cd8a2342c5370fde5df1a7140
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/39525bbff413519199d1cf2c564d62b9c3c7736e b/test/core/end2end/fuzzers/api_fuzzer_corpus/39525bbff413519199d1cf2c564d62b9c3c7736e
new file mode 100644
index 0000000..6e61ae8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/39525bbff413519199d1cf2c564d62b9c3c7736e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/39b6daa9ae088667c5080709ca829cf51e66212d b/test/core/end2end/fuzzers/api_fuzzer_corpus/39b6daa9ae088667c5080709ca829cf51e66212d
new file mode 100644
index 0000000..e72f341
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/39b6daa9ae088667c5080709ca829cf51e66212d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3a90fbc998ad7219e447db6155e6174e0117dd49 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a90fbc998ad7219e447db6155e6174e0117dd49
new file mode 100644
index 0000000..7c2bacc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a90fbc998ad7219e447db6155e6174e0117dd49
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3af9522626ddfeb1ef461e3ba0f397ea4b2d99fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/3af9522626ddfeb1ef461e3ba0f397ea4b2d99fb
new file mode 100644
index 0000000..bbbacc8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3af9522626ddfeb1ef461e3ba0f397ea4b2d99fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3b60e6663ac7ceaa40f91d3a68fcb9c35e3e99b8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b60e6663ac7ceaa40f91d3a68fcb9c35e3e99b8
new file mode 100644
index 0000000..99a6322
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b60e6663ac7ceaa40f91d3a68fcb9c35e3e99b8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3bdfaad171c20468a866329355621cd579eff21c b/test/core/end2end/fuzzers/api_fuzzer_corpus/3bdfaad171c20468a866329355621cd579eff21c
new file mode 100644
index 0000000..a48c034
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3bdfaad171c20468a866329355621cd579eff21c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c18f7c2d8fef6f119fe5bdbb5d191a92c627cb3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c18f7c2d8fef6f119fe5bdbb5d191a92c627cb3
new file mode 100644
index 0000000..d9450a9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c18f7c2d8fef6f119fe5bdbb5d191a92c627cb3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c933aea09501c81d7e065c671cdc3bd55f8caf9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c933aea09501c81d7e065c671cdc3bd55f8caf9
new file mode 100644
index 0000000..d09a0cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c933aea09501c81d7e065c671cdc3bd55f8caf9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac139b58decec7c0d1f1318e8f1f28f9650c19 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac139b58decec7c0d1f1318e8f1f28f9650c19
new file mode 100644
index 0000000..60b2a10
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac139b58decec7c0d1f1318e8f1f28f9650c19
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3cd19f8138a81f242cb92212df2b4812cde8385a b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cd19f8138a81f242cb92212df2b4812cde8385a
new file mode 100644
index 0000000..f9395cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cd19f8138a81f242cb92212df2b4812cde8385a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3d7d13b272c46ccceca36729e9893e5142961fd3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d7d13b272c46ccceca36729e9893e5142961fd3
new file mode 100644
index 0000000..a46741e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d7d13b272c46ccceca36729e9893e5142961fd3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3d9534f373e79edd704cc9529600efd62451fb78 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d9534f373e79edd704cc9529600efd62451fb78
new file mode 100644
index 0000000..7ce51c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d9534f373e79edd704cc9529600efd62451fb78
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3e4c1755d1ad78103f10c2af7c7d2f86326f02f6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e4c1755d1ad78103f10c2af7c7d2f86326f02f6
new file mode 100644
index 0000000..ba043af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e4c1755d1ad78103f10c2af7c7d2f86326f02f6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3e8bef87bb89525914b5e7964969a66eabc78eee b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e8bef87bb89525914b5e7964969a66eabc78eee
new file mode 100644
index 0000000..673ce21
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e8bef87bb89525914b5e7964969a66eabc78eee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3fada97db682f675597cb58c5d43a72e283ab960 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3fada97db682f675597cb58c5d43a72e283ab960
new file mode 100644
index 0000000..2acdaaa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3fada97db682f675597cb58c5d43a72e283ab960
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/40fb9f1d9086ace2de0ad59648d196ba0705ae00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/40fb9f1d9086ace2de0ad59648d196ba0705ae00
new file mode 100644
index 0000000..935f92b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/40fb9f1d9086ace2de0ad59648d196ba0705ae00
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/41921ba00dfc038778074b1af81104555ca74927 b/test/core/end2end/fuzzers/api_fuzzer_corpus/41921ba00dfc038778074b1af81104555ca74927
new file mode 100644
index 0000000..c1ec996
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/41921ba00dfc038778074b1af81104555ca74927
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/41de80653b78b98f5caa7f6d00a96d72bc245068 b/test/core/end2end/fuzzers/api_fuzzer_corpus/41de80653b78b98f5caa7f6d00a96d72bc245068
new file mode 100644
index 0000000..101bb72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/41de80653b78b98f5caa7f6d00a96d72bc245068
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4212d95c0bfdf34b9c7fbd05bc732fa1bbb226ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/4212d95c0bfdf34b9c7fbd05bc732fa1bbb226ce
new file mode 100644
index 0000000..7f90387
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4212d95c0bfdf34b9c7fbd05bc732fa1bbb226ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4236180c7d6f2edba5355b79bbe1a5c16266dd95 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4236180c7d6f2edba5355b79bbe1a5c16266dd95
new file mode 100644
index 0000000..9bd671d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4236180c7d6f2edba5355b79bbe1a5c16266dd95
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/428b5b04a92ad6c28fc38451236c85338b9f8ce0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/428b5b04a92ad6c28fc38451236c85338b9f8ce0
new file mode 100644
index 0000000..9da7676
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/428b5b04a92ad6c28fc38451236c85338b9f8ce0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42a92ac224829067ee7dbadafb777bd38f076c6f b/test/core/end2end/fuzzers/api_fuzzer_corpus/42a92ac224829067ee7dbadafb777bd38f076c6f
new file mode 100644
index 0000000..8b800ca
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42a92ac224829067ee7dbadafb777bd38f076c6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42c2e90f2e228d6bec0d81e55f08647a2d651bbe b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c2e90f2e228d6bec0d81e55f08647a2d651bbe
new file mode 100644
index 0000000..6ea6ab3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c2e90f2e228d6bec0d81e55f08647a2d651bbe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42c50f9543819ff7f440a7ac660cea374355c455 b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c50f9543819ff7f440a7ac660cea374355c455
new file mode 100644
index 0000000..9e377e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c50f9543819ff7f440a7ac660cea374355c455
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42c5f1965243b4bdf0212123d3430010bdacefaa b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c5f1965243b4bdf0212123d3430010bdacefaa
new file mode 100644
index 0000000..93385ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42c5f1965243b4bdf0212123d3430010bdacefaa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4305b19e8a214d2cf47436d964d52d10e430575f b/test/core/end2end/fuzzers/api_fuzzer_corpus/4305b19e8a214d2cf47436d964d52d10e430575f
new file mode 100644
index 0000000..33f855c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4305b19e8a214d2cf47436d964d52d10e430575f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43646936116c18140ff0f01306d16280943eedac b/test/core/end2end/fuzzers/api_fuzzer_corpus/43646936116c18140ff0f01306d16280943eedac
new file mode 100644
index 0000000..43d8418
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43646936116c18140ff0f01306d16280943eedac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43874e2bb721b485a93d80b7f1c3e3630f746b02 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43874e2bb721b485a93d80b7f1c3e3630f746b02
new file mode 100644
index 0000000..272ee2c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43874e2bb721b485a93d80b7f1c3e3630f746b02
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43ed8f46ad700ddd4c2a7a15f0cd209954f0a774 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43ed8f46ad700ddd4c2a7a15f0cd209954f0a774
new file mode 100644
index 0000000..722278a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43ed8f46ad700ddd4c2a7a15f0cd209954f0a774
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43f79e748c5da73a13555b00cf5050af68f07829 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43f79e748c5da73a13555b00cf5050af68f07829
new file mode 100644
index 0000000..e538915
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43f79e748c5da73a13555b00cf5050af68f07829
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43ff758aba2eca1e355f0062ca8fa2dcc8edc69c b/test/core/end2end/fuzzers/api_fuzzer_corpus/43ff758aba2eca1e355f0062ca8fa2dcc8edc69c
new file mode 100644
index 0000000..6a84f69
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43ff758aba2eca1e355f0062ca8fa2dcc8edc69c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4427b547b6693c39f08ba67c5d2ad012d5088f83 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4427b547b6693c39f08ba67c5d2ad012d5088f83
new file mode 100644
index 0000000..0be2c14
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4427b547b6693c39f08ba67c5d2ad012d5088f83
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/442bb0df4955b8dc95cc69af79a522a04c23dfe1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/442bb0df4955b8dc95cc69af79a522a04c23dfe1
new file mode 100644
index 0000000..1564b00
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/442bb0df4955b8dc95cc69af79a522a04c23dfe1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/44378830a865936e205bb757a69bdf8d788bf26e b/test/core/end2end/fuzzers/api_fuzzer_corpus/44378830a865936e205bb757a69bdf8d788bf26e
new file mode 100644
index 0000000..c320596
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/44378830a865936e205bb757a69bdf8d788bf26e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4471ee009359844e7600175546a3b36a21329666 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4471ee009359844e7600175546a3b36a21329666
new file mode 100644
index 0000000..b41b650
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4471ee009359844e7600175546a3b36a21329666
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/454fb5eab23aacdba559ed9a9a36941732eb3276 b/test/core/end2end/fuzzers/api_fuzzer_corpus/454fb5eab23aacdba559ed9a9a36941732eb3276
new file mode 100644
index 0000000..55ab577
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/454fb5eab23aacdba559ed9a9a36941732eb3276
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/461949a48f4f2234cce6bfc1476bc9fd96552c0e b/test/core/end2end/fuzzers/api_fuzzer_corpus/461949a48f4f2234cce6bfc1476bc9fd96552c0e
new file mode 100644
index 0000000..9ec340d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/461949a48f4f2234cce6bfc1476bc9fd96552c0e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/462ae7e1d7eb4a4d8b4d5daaa1422b7cf835e127 b/test/core/end2end/fuzzers/api_fuzzer_corpus/462ae7e1d7eb4a4d8b4d5daaa1422b7cf835e127
new file mode 100644
index 0000000..66adcdf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/462ae7e1d7eb4a4d8b4d5daaa1422b7cf835e127
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/46325fcd7a3a718f2188f49e28ad9d0c9dcd06a9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/46325fcd7a3a718f2188f49e28ad9d0c9dcd06a9
new file mode 100644
index 0000000..99748fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/46325fcd7a3a718f2188f49e28ad9d0c9dcd06a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4667156173c437c62fdea99a199f3aed0b504fe0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4667156173c437c62fdea99a199f3aed0b504fe0
new file mode 100644
index 0000000..1b98c74
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4667156173c437c62fdea99a199f3aed0b504fe0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/46f88af92fbd99c386bd24d8a045a9a9c2469d53 b/test/core/end2end/fuzzers/api_fuzzer_corpus/46f88af92fbd99c386bd24d8a045a9a9c2469d53
new file mode 100644
index 0000000..6e6744a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/46f88af92fbd99c386bd24d8a045a9a9c2469d53
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4799a2aacdba08bd3e418c5659060829a997d715 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4799a2aacdba08bd3e418c5659060829a997d715
new file mode 100644
index 0000000..e4d5db3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4799a2aacdba08bd3e418c5659060829a997d715
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/47f2ead1b9cd99a8603dc5fd583afe3d4287deab b/test/core/end2end/fuzzers/api_fuzzer_corpus/47f2ead1b9cd99a8603dc5fd583afe3d4287deab
new file mode 100644
index 0000000..f4d2647
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/47f2ead1b9cd99a8603dc5fd583afe3d4287deab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/485410954a625f5749bce6ae923a620371542ed8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/485410954a625f5749bce6ae923a620371542ed8
new file mode 100644
index 0000000..376c38e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/485410954a625f5749bce6ae923a620371542ed8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/48f56289592da153b3c50bcc26ad6d4d3a7e443b b/test/core/end2end/fuzzers/api_fuzzer_corpus/48f56289592da153b3c50bcc26ad6d4d3a7e443b
new file mode 100644
index 0000000..b31f82d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/48f56289592da153b3c50bcc26ad6d4d3a7e443b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/49d816ae44b329820f47979c5790eebc8eadafd7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/49d816ae44b329820f47979c5790eebc8eadafd7
new file mode 100644
index 0000000..d75351c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/49d816ae44b329820f47979c5790eebc8eadafd7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a2ee017facf4df1929e7db4b34b12018b64461c b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a2ee017facf4df1929e7db4b34b12018b64461c
new file mode 100644
index 0000000..7a7c0e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a2ee017facf4df1929e7db4b34b12018b64461c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21
new file mode 100644
index 0000000..ac5edb5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a97016bb83b0db1c51fbb4d4f9c909dd85bdb41 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a97016bb83b0db1c51fbb4d4f9c909dd85bdb41
new file mode 100644
index 0000000..a3cea9c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a97016bb83b0db1c51fbb4d4f9c909dd85bdb41
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4b011706723e645407b871241c2c11004103d628 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b011706723e645407b871241c2c11004103d628
new file mode 100644
index 0000000..9d30e8f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b011706723e645407b871241c2c11004103d628
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4bedfc6d01a2d6bc0911d48123d6b8b30a46732e b/test/core/end2end/fuzzers/api_fuzzer_corpus/4bedfc6d01a2d6bc0911d48123d6b8b30a46732e
new file mode 100644
index 0000000..9e55ca6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4bedfc6d01a2d6bc0911d48123d6b8b30a46732e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4c03f9d60bfc5a2ab41c1703672a339838890ef3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c03f9d60bfc5a2ab41c1703672a339838890ef3
new file mode 100644
index 0000000..2d42a41
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c03f9d60bfc5a2ab41c1703672a339838890ef3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4c34bbb26218f40a8ea1bafc8c50cd814a781cd2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c34bbb26218f40a8ea1bafc8c50cd814a781cd2
new file mode 100644
index 0000000..f632c98
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c34bbb26218f40a8ea1bafc8c50cd814a781cd2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4c6258b5299bd03560e292fcf3008efc60bc6cd1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c6258b5299bd03560e292fcf3008efc60bc6cd1
new file mode 100644
index 0000000..e37ca84
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4c6258b5299bd03560e292fcf3008efc60bc6cd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d7b5b98536de248387605efd813ba23b8b613dd b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d7b5b98536de248387605efd813ba23b8b613dd
new file mode 100644
index 0000000..46684b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d7b5b98536de248387605efd813ba23b8b613dd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d800cf62e39478c1bc1db8222a8d810fff6ad85 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d800cf62e39478c1bc1db8222a8d810fff6ad85
new file mode 100644
index 0000000..b360407
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d800cf62e39478c1bc1db8222a8d810fff6ad85
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d81efc0d5945caada326e2f6e55167120f0d3ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d81efc0d5945caada326e2f6e55167120f0d3ce
new file mode 100644
index 0000000..cb4341e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d81efc0d5945caada326e2f6e55167120f0d3ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4ea18756816848daf5e799ce1d75ecf52353eb08 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ea18756816848daf5e799ce1d75ecf52353eb08
new file mode 100644
index 0000000..c1f4a81
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ea18756816848daf5e799ce1d75ecf52353eb08
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4f320381bfd3927493db8037238bdce1766c68ee b/test/core/end2end/fuzzers/api_fuzzer_corpus/4f320381bfd3927493db8037238bdce1766c68ee
new file mode 100644
index 0000000..a1d23bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4f320381bfd3927493db8037238bdce1766c68ee
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/50a96367b6a52c58a36364f4b1ec0583c7f315a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/50a96367b6a52c58a36364f4b1ec0583c7f315a5
new file mode 100644
index 0000000..92710c0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/50a96367b6a52c58a36364f4b1ec0583c7f315a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5151ad7147bbb75b1b377ce03f4ef5ef0f4f1c82 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5151ad7147bbb75b1b377ce03f4ef5ef0f4f1c82
new file mode 100644
index 0000000..4b6ca5d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5151ad7147bbb75b1b377ce03f4ef5ef0f4f1c82
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5220909c423d2b321e8459355c965fb330288565 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5220909c423d2b321e8459355c965fb330288565
new file mode 100644
index 0000000..50fdc94
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5220909c423d2b321e8459355c965fb330288565
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/52b5c86f262d46624b2211151a38cbd69c705734 b/test/core/end2end/fuzzers/api_fuzzer_corpus/52b5c86f262d46624b2211151a38cbd69c705734
new file mode 100644
index 0000000..63a7c37
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/52b5c86f262d46624b2211151a38cbd69c705734
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5394ae134e9023432ac137789815e2b24d1bab3b b/test/core/end2end/fuzzers/api_fuzzer_corpus/5394ae134e9023432ac137789815e2b24d1bab3b
new file mode 100644
index 0000000..0ee6048
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5394ae134e9023432ac137789815e2b24d1bab3b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/53e9f9a4b0347651b3833c3e153e743a1194e0fa b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e9f9a4b0347651b3833c3e153e743a1194e0fa
new file mode 100644
index 0000000..a52d56a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e9f9a4b0347651b3833c3e153e743a1194e0fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/543ea879faab347874ad5e297684a62a1555e1ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/543ea879faab347874ad5e297684a62a1555e1ab
new file mode 100644
index 0000000..a457d0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/543ea879faab347874ad5e297684a62a1555e1ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/548190b9eb539e0841bcdd6e2c095cbef6ebd119 b/test/core/end2end/fuzzers/api_fuzzer_corpus/548190b9eb539e0841bcdd6e2c095cbef6ebd119
new file mode 100644
index 0000000..65c6467
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/548190b9eb539e0841bcdd6e2c095cbef6ebd119
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/54d5ac6cc4bd944e60b7464e36c5d1b144c17da4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/54d5ac6cc4bd944e60b7464e36c5d1b144c17da4
new file mode 100644
index 0000000..aae4aef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/54d5ac6cc4bd944e60b7464e36c5d1b144c17da4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5515fa05b890973031b0e2cc8c2925f3974e2821 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5515fa05b890973031b0e2cc8c2925f3974e2821
new file mode 100644
index 0000000..53c4227
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5515fa05b890973031b0e2cc8c2925f3974e2821
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/560fe3fe0bb266ccb8c59ce19302bce23835097d b/test/core/end2end/fuzzers/api_fuzzer_corpus/560fe3fe0bb266ccb8c59ce19302bce23835097d
new file mode 100644
index 0000000..7959ac9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/560fe3fe0bb266ccb8c59ce19302bce23835097d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/56ac47e07bf3f42310773a4c66ee9d3afc27a8a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/56ac47e07bf3f42310773a4c66ee9d3afc27a8a3
new file mode 100644
index 0000000..c362e6a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/56ac47e07bf3f42310773a4c66ee9d3afc27a8a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/570215c70de40add2ad62bed9ce47f8b6b231de6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/570215c70de40add2ad62bed9ce47f8b6b231de6
new file mode 100644
index 0000000..c08ff2b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/570215c70de40add2ad62bed9ce47f8b6b231de6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/572ab3983e406a82325f02edfdd7981d040cfbdb b/test/core/end2end/fuzzers/api_fuzzer_corpus/572ab3983e406a82325f02edfdd7981d040cfbdb
new file mode 100644
index 0000000..54b4bee
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/572ab3983e406a82325f02edfdd7981d040cfbdb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/573665d817a96a324fb8ba40a06425f572327b78 b/test/core/end2end/fuzzers/api_fuzzer_corpus/573665d817a96a324fb8ba40a06425f572327b78
new file mode 100644
index 0000000..0c3d482
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/573665d817a96a324fb8ba40a06425f572327b78
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57bc1a4501ceb31b4ead1c2428798be073eb9db3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/57bc1a4501ceb31b4ead1c2428798be073eb9db3
new file mode 100644
index 0000000..d9ef9bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57bc1a4501ceb31b4ead1c2428798be073eb9db3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/58c57e0ef4c2a630150f53ccdc2bfa798d5b9eae b/test/core/end2end/fuzzers/api_fuzzer_corpus/58c57e0ef4c2a630150f53ccdc2bfa798d5b9eae
new file mode 100644
index 0000000..4408087
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/58c57e0ef4c2a630150f53ccdc2bfa798d5b9eae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/59de0a42d012ca3dd8b7fa2f1b1c6642cb86fad4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/59de0a42d012ca3dd8b7fa2f1b1c6642cb86fad4
new file mode 100644
index 0000000..854dd1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/59de0a42d012ca3dd8b7fa2f1b1c6642cb86fad4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a1d370abacb9f46fa966c8e58992897606a7900 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a1d370abacb9f46fa966c8e58992897606a7900
new file mode 100644
index 0000000..ae5f908
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a1d370abacb9f46fa966c8e58992897606a7900
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a34e7fd2ff3f8e32ce85138931a387dc5f15db0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a34e7fd2ff3f8e32ce85138931a387dc5f15db0
new file mode 100644
index 0000000..3f75486
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a34e7fd2ff3f8e32ce85138931a387dc5f15db0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3d25f74f7629c675be11faaea35921229b8757 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3d25f74f7629c675be11faaea35921229b8757
new file mode 100644
index 0000000..c1aa94b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5a3d25f74f7629c675be11faaea35921229b8757
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ae4d5439ec6910a5fcd9c41f20ae843942853c6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ae4d5439ec6910a5fcd9c41f20ae843942853c6
new file mode 100644
index 0000000..b9b9fb9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ae4d5439ec6910a5fcd9c41f20ae843942853c6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5b3f6f20f348cc4e5fb07cdb6e8614ca24f2cf13 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5b3f6f20f348cc4e5fb07cdb6e8614ca24f2cf13
new file mode 100644
index 0000000..1cfa196
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5b3f6f20f348cc4e5fb07cdb6e8614ca24f2cf13
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5c117dbd5d3146fd94c667f15f4c006fea88d14d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c117dbd5d3146fd94c667f15f4c006fea88d14d
new file mode 100644
index 0000000..03cd401
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c117dbd5d3146fd94c667f15f4c006fea88d14d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5c388b60e622e14c9abfb5b46c65207a319e09e4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c388b60e622e14c9abfb5b46c65207a319e09e4
new file mode 100644
index 0000000..417ac89
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c388b60e622e14c9abfb5b46c65207a319e09e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5c43f3a5de9c581693432dbb2ad604550c3948f5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c43f3a5de9c581693432dbb2ad604550c3948f5
new file mode 100644
index 0000000..13b07bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c43f3a5de9c581693432dbb2ad604550c3948f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5cce719931cf1f07536401134de4325b942be87d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cce719931cf1f07536401134de4325b942be87d
new file mode 100644
index 0000000..19c6d54
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cce719931cf1f07536401134de4325b942be87d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5cd55495dee689728feee959bcb09e2ab13d013d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cd55495dee689728feee959bcb09e2ab13d013d
new file mode 100644
index 0000000..48291a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cd55495dee689728feee959bcb09e2ab13d013d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5cf8b4c70476c124711e731cd2e00f67906bd457 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cf8b4c70476c124711e731cd2e00f67906bd457
new file mode 100644
index 0000000..8d9455f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cf8b4c70476c124711e731cd2e00f67906bd457
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5d5ce71ab1258e014e06e6a2edb94a47a4ae1b35 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d5ce71ab1258e014e06e6a2edb94a47a4ae1b35
new file mode 100644
index 0000000..5962d64
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d5ce71ab1258e014e06e6a2edb94a47a4ae1b35
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5d76fdb98fb38243a1f1c5f96d31ece34c5a91b7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d76fdb98fb38243a1f1c5f96d31ece34c5a91b7
new file mode 100644
index 0000000..730cac7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5d76fdb98fb38243a1f1c5f96d31ece34c5a91b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5da437d4fd58607deeed34bcb21accece71a056b b/test/core/end2end/fuzzers/api_fuzzer_corpus/5da437d4fd58607deeed34bcb21accece71a056b
new file mode 100644
index 0000000..e751aa0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5da437d4fd58607deeed34bcb21accece71a056b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddcbde7afa43e7fe4e44ef1470fc0c282873cae b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddcbde7afa43e7fe4e44ef1470fc0c282873cae
new file mode 100644
index 0000000..33e7ec9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddcbde7afa43e7fe4e44ef1470fc0c282873cae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5e880db498f9baae544cdbc23476873d8766ac58 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e880db498f9baae544cdbc23476873d8766ac58
new file mode 100644
index 0000000..b9e4608
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e880db498f9baae544cdbc23476873d8766ac58
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5eae70ef8ab19fead6a9275e3e40df6b201159b1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5eae70ef8ab19fead6a9275e3e40df6b201159b1
new file mode 100644
index 0000000..8790cf4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5eae70ef8ab19fead6a9275e3e40df6b201159b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed431181bedd9a496aa3bb2330957c621f1443d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed431181bedd9a496aa3bb2330957c621f1443d
new file mode 100644
index 0000000..a143c3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed431181bedd9a496aa3bb2330957c621f1443d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed8998cfc22cce008e3988b3591b1c9ddbfaa75 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed8998cfc22cce008e3988b3591b1c9ddbfaa75
new file mode 100644
index 0000000..4d597e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ed8998cfc22cce008e3988b3591b1c9ddbfaa75
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f07e5246d765494ee26c689072ab3ced452f30e b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f07e5246d765494ee26c689072ab3ced452f30e
new file mode 100644
index 0000000..fe4b4c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f07e5246d765494ee26c689072ab3ced452f30e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14
new file mode 100644
index 0000000..1b7cd7b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f7eee027cbd6ae8e989150d9bd8a4fd39654c01 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f7eee027cbd6ae8e989150d9bd8a4fd39654c01
new file mode 100644
index 0000000..7fbd858
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f7eee027cbd6ae8e989150d9bd8a4fd39654c01
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/600096fe00d5f67726674fb9b0d2a6621a25e79c b/test/core/end2end/fuzzers/api_fuzzer_corpus/600096fe00d5f67726674fb9b0d2a6621a25e79c
new file mode 100644
index 0000000..f456358
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/600096fe00d5f67726674fb9b0d2a6621a25e79c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6123f6116f3cacb4aabdbe26aed24ed0981d6c1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/6123f6116f3cacb4aabdbe26aed24ed0981d6c1c
new file mode 100644
index 0000000..292cb9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6123f6116f3cacb4aabdbe26aed24ed0981d6c1c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/617a2a3f6b6d5d53993db606a8818235ae8d9b96 b/test/core/end2end/fuzzers/api_fuzzer_corpus/617a2a3f6b6d5d53993db606a8818235ae8d9b96
new file mode 100644
index 0000000..4a6a220
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/617a2a3f6b6d5d53993db606a8818235ae8d9b96
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/617ef08330c0e852f9aae6c63ddc5893b8b2c722 b/test/core/end2end/fuzzers/api_fuzzer_corpus/617ef08330c0e852f9aae6c63ddc5893b8b2c722
new file mode 100644
index 0000000..efaa4a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/617ef08330c0e852f9aae6c63ddc5893b8b2c722
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/618e64836dc7f374745be963b7b3c62cc02ae2ca b/test/core/end2end/fuzzers/api_fuzzer_corpus/618e64836dc7f374745be963b7b3c62cc02ae2ca
new file mode 100644
index 0000000..4775cd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/618e64836dc7f374745be963b7b3c62cc02ae2ca
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/61ce843c87f7bda1fabcb6ae3f41e85e6e2332ac b/test/core/end2end/fuzzers/api_fuzzer_corpus/61ce843c87f7bda1fabcb6ae3f41e85e6e2332ac
new file mode 100644
index 0000000..6e46ea8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/61ce843c87f7bda1fabcb6ae3f41e85e6e2332ac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417 b/test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417
new file mode 100644
index 0000000..61d118d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c
new file mode 100644
index 0000000..f1e6ccc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4
new file mode 100644
index 0000000..7ecbf72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3
new file mode 100644
index 0000000..44e84a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d b/test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d
new file mode 100644
index 0000000..25ea6ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25 b/test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25
new file mode 100644
index 0000000..d2087ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640 b/test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640
new file mode 100644
index 0000000..0826bbc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5
new file mode 100644
index 0000000..e59a835
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24 b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24
new file mode 100644
index 0000000..b3aac99
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81
new file mode 100644
index 0000000..600f855
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0
new file mode 100644
index 0000000..61529df
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6639deedbf04eceba6017f712b287235540b5528 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6639deedbf04eceba6017f712b287235540b5528
new file mode 100644
index 0000000..489843e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6639deedbf04eceba6017f712b287235540b5528
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/665d7b4f8082be87864e6ad3a6a3faa1d52ad6e5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/665d7b4f8082be87864e6ad3a6a3faa1d52ad6e5
new file mode 100644
index 0000000..899f662
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/665d7b4f8082be87864e6ad3a6a3faa1d52ad6e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/66f0ed73b2d4ca3edbd23d5b669e75e4d0ffd292 b/test/core/end2end/fuzzers/api_fuzzer_corpus/66f0ed73b2d4ca3edbd23d5b669e75e4d0ffd292
new file mode 100644
index 0000000..924c8ac
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/66f0ed73b2d4ca3edbd23d5b669e75e4d0ffd292
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6722929b4924f4d50ccfb999460e9a31ca104b4c b/test/core/end2end/fuzzers/api_fuzzer_corpus/6722929b4924f4d50ccfb999460e9a31ca104b4c
new file mode 100644
index 0000000..10cebea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6722929b4924f4d50ccfb999460e9a31ca104b4c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6868e669f4b9a77ae5227767ec455fe6f82e55a1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6868e669f4b9a77ae5227767ec455fe6f82e55a1
new file mode 100644
index 0000000..64d6f6d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6868e669f4b9a77ae5227767ec455fe6f82e55a1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6887af467b343d6e1a8125ef10eb0a630f2dc06d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6887af467b343d6e1a8125ef10eb0a630f2dc06d
new file mode 100644
index 0000000..f3d89db
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6887af467b343d6e1a8125ef10eb0a630f2dc06d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/68c65dc60f887050eb8cd7f946bf37aea2ade9f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/68c65dc60f887050eb8cd7f946bf37aea2ade9f2
new file mode 100644
index 0000000..f94aa4e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/68c65dc60f887050eb8cd7f946bf37aea2ade9f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/68f9d39b83bbc7cb4f743c8814800e6692988897 b/test/core/end2end/fuzzers/api_fuzzer_corpus/68f9d39b83bbc7cb4f743c8814800e6692988897
new file mode 100644
index 0000000..ef065af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/68f9d39b83bbc7cb4f743c8814800e6692988897
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/69d0f8b4a9452d11620c7d3c1fa532a618d65858 b/test/core/end2end/fuzzers/api_fuzzer_corpus/69d0f8b4a9452d11620c7d3c1fa532a618d65858
new file mode 100644
index 0000000..792443b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/69d0f8b4a9452d11620c7d3c1fa532a618d65858
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6a1d877fe1eed1199511b8f28889d8f17665708e b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a1d877fe1eed1199511b8f28889d8f17665708e
new file mode 100644
index 0000000..4e4ac64
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a1d877fe1eed1199511b8f28889d8f17665708e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ac88da4119df5e1592a05bac7ecb92af59dc1d1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ac88da4119df5e1592a05bac7ecb92af59dc1d1
new file mode 100644
index 0000000..d86c3d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ac88da4119df5e1592a05bac7ecb92af59dc1d1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6b1e10a936df3b42720ebc9179fb74aa147f8b14 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6b1e10a936df3b42720ebc9179fb74aa147f8b14
new file mode 100644
index 0000000..2c01f4f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6b1e10a936df3b42720ebc9179fb74aa147f8b14
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6bd27df0dc9a3f73108de7bad443433aa5ee1175 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6bd27df0dc9a3f73108de7bad443433aa5ee1175
new file mode 100644
index 0000000..47e0006
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6bd27df0dc9a3f73108de7bad443433aa5ee1175
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6c5707e8b1aa9a70ec87014cd660df4a7b910ee3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c5707e8b1aa9a70ec87014cd660df4a7b910ee3
new file mode 100644
index 0000000..3ff6967
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c5707e8b1aa9a70ec87014cd660df4a7b910ee3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6c91623f5a30f65110a4083897bad2882f032c51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c91623f5a30f65110a4083897bad2882f032c51
new file mode 100644
index 0000000..9a56cb7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c91623f5a30f65110a4083897bad2882f032c51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6c9b144f4e6dae6944b524a077dde07ac79e58d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c9b144f4e6dae6944b524a077dde07ac79e58d5
new file mode 100644
index 0000000..dc4750c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c9b144f4e6dae6944b524a077dde07ac79e58d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ca83e5d3f4544a14da513dc798f02464febdcd8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ca83e5d3f4544a14da513dc798f02464febdcd8
new file mode 100644
index 0000000..43b098b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ca83e5d3f4544a14da513dc798f02464febdcd8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce9895c780428861d12440946508c6641352544 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce9895c780428861d12440946508c6641352544
new file mode 100644
index 0000000..7d51c94
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce9895c780428861d12440946508c6641352544
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6df1c575d7f8fdf5593f1f60d9dc540d018fc58c b/test/core/end2end/fuzzers/api_fuzzer_corpus/6df1c575d7f8fdf5593f1f60d9dc540d018fc58c
new file mode 100644
index 0000000..9675887
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6df1c575d7f8fdf5593f1f60d9dc540d018fc58c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6e97f4e782ca976d4890199d48fcfd64173e24f9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e97f4e782ca976d4890199d48fcfd64173e24f9
new file mode 100644
index 0000000..ee42072
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e97f4e782ca976d4890199d48fcfd64173e24f9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6f0bbfce7c5027932fb0f809494413e12a4ad3c1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f0bbfce7c5027932fb0f809494413e12a4ad3c1
new file mode 100644
index 0000000..2f9cfea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f0bbfce7c5027932fb0f809494413e12a4ad3c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6f39da8f5bbae89a13dd36755f7b3c4a30c25833 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f39da8f5bbae89a13dd36755f7b3c4a30c25833
new file mode 100644
index 0000000..98b2635
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f39da8f5bbae89a13dd36755f7b3c4a30c25833
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6fa93aadbb6ecdc32c9111be7692ec28ec11be72 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fa93aadbb6ecdc32c9111be7692ec28ec11be72
new file mode 100644
index 0000000..f7b2e99
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fa93aadbb6ecdc32c9111be7692ec28ec11be72
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6fb7b01c1b363390eb9188bcac05f8f11e20c01d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fb7b01c1b363390eb9188bcac05f8f11e20c01d
new file mode 100644
index 0000000..792e812
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fb7b01c1b363390eb9188bcac05f8f11e20c01d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6fbbaf9f6f49fabad4a0e47cea9e4048d8f130ed b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fbbaf9f6f49fabad4a0e47cea9e4048d8f130ed
new file mode 100644
index 0000000..e0a6317
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fbbaf9f6f49fabad4a0e47cea9e4048d8f130ed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6fe041f1468b495d3186da906f9a5091e5761387 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fe041f1468b495d3186da906f9a5091e5761387
new file mode 100644
index 0000000..ea9c354
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fe041f1468b495d3186da906f9a5091e5761387
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6fff95a8d3566b2721fa46e9828b47635f13d9ef b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fff95a8d3566b2721fa46e9828b47635f13d9ef
new file mode 100644
index 0000000..ec7a56d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6fff95a8d3566b2721fa46e9828b47635f13d9ef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/700f56e26286daf472d371effb9bca13fffa3d77 b/test/core/end2end/fuzzers/api_fuzzer_corpus/700f56e26286daf472d371effb9bca13fffa3d77
new file mode 100644
index 0000000..0c6b8c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/700f56e26286daf472d371effb9bca13fffa3d77
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/705c87b99197c87eb2ed148f8b3fdc60f8616f15 b/test/core/end2end/fuzzers/api_fuzzer_corpus/705c87b99197c87eb2ed148f8b3fdc60f8616f15
new file mode 100644
index 0000000..d8930c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/705c87b99197c87eb2ed148f8b3fdc60f8616f15
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/718d23058d5c805a2984c087cd89f9cb6af065b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/718d23058d5c805a2984c087cd89f9cb6af065b4
new file mode 100644
index 0000000..9282b0a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/718d23058d5c805a2984c087cd89f9cb6af065b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7217d93c1da3ae8ed085a5e6988227dcf430cd89 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7217d93c1da3ae8ed085a5e6988227dcf430cd89
new file mode 100644
index 0000000..0f64b02
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7217d93c1da3ae8ed085a5e6988227dcf430cd89
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/724063b7a5ee36246d72923e776331487434b81a b/test/core/end2end/fuzzers/api_fuzzer_corpus/724063b7a5ee36246d72923e776331487434b81a
new file mode 100644
index 0000000..a554b8f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/724063b7a5ee36246d72923e776331487434b81a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72a79517b8f9b57f62dc1203a6b5eefadf27c088 b/test/core/end2end/fuzzers/api_fuzzer_corpus/72a79517b8f9b57f62dc1203a6b5eefadf27c088
new file mode 100644
index 0000000..0e79558
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72a79517b8f9b57f62dc1203a6b5eefadf27c088
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72f71befa8ebb4b2c1842aec78d840b2a4abdb85 b/test/core/end2end/fuzzers/api_fuzzer_corpus/72f71befa8ebb4b2c1842aec78d840b2a4abdb85
new file mode 100644
index 0000000..2840279
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72f71befa8ebb4b2c1842aec78d840b2a4abdb85
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/73a6e07089ee011746c1ec3146b8a1b4b82c835e b/test/core/end2end/fuzzers/api_fuzzer_corpus/73a6e07089ee011746c1ec3146b8a1b4b82c835e
new file mode 100644
index 0000000..0a6411f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/73a6e07089ee011746c1ec3146b8a1b4b82c835e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7421d8acd877abd9d437ad447dfae29893cd2f37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7421d8acd877abd9d437ad447dfae29893cd2f37
new file mode 100644
index 0000000..7d730ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7421d8acd877abd9d437ad447dfae29893cd2f37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/746d9837f0fc3c989b7fe0585b8365478f1c21fc b/test/core/end2end/fuzzers/api_fuzzer_corpus/746d9837f0fc3c989b7fe0585b8365478f1c21fc
new file mode 100644
index 0000000..be67234
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/746d9837f0fc3c989b7fe0585b8365478f1c21fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/746ecd23f1c41206dd4180a7afb032411f315d73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/746ecd23f1c41206dd4180a7afb032411f315d73
new file mode 100644
index 0000000..8d7fa42
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/746ecd23f1c41206dd4180a7afb032411f315d73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7487f56a435277d9bd7ef38d361e8ad7cdf62375 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7487f56a435277d9bd7ef38d361e8ad7cdf62375
new file mode 100644
index 0000000..1f07e58
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7487f56a435277d9bd7ef38d361e8ad7cdf62375
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/75755ae5cb0ae4f711dd15925f9f681d23408bb8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/75755ae5cb0ae4f711dd15925f9f681d23408bb8
new file mode 100644
index 0000000..94f068b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/75755ae5cb0ae4f711dd15925f9f681d23408bb8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/774a64c60765d78b3b980ff9a6538219d6908a3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/774a64c60765d78b3b980ff9a6538219d6908a3d
new file mode 100644
index 0000000..d84b622
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/774a64c60765d78b3b980ff9a6538219d6908a3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/783b1f17ae90eba0ff7728e767b56ea6885e0b28 b/test/core/end2end/fuzzers/api_fuzzer_corpus/783b1f17ae90eba0ff7728e767b56ea6885e0b28
new file mode 100644
index 0000000..3fb16c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/783b1f17ae90eba0ff7728e767b56ea6885e0b28
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/78499fa2980dce2fde92b74421f486bf544cfb8f b/test/core/end2end/fuzzers/api_fuzzer_corpus/78499fa2980dce2fde92b74421f486bf544cfb8f
new file mode 100644
index 0000000..0ad9591
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/78499fa2980dce2fde92b74421f486bf544cfb8f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/788f18727a0aeb5e200527bca7c889c9954be343 b/test/core/end2end/fuzzers/api_fuzzer_corpus/788f18727a0aeb5e200527bca7c889c9954be343
new file mode 100644
index 0000000..e8bc498
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/788f18727a0aeb5e200527bca7c889c9954be343
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/78c3bbeaeb266aac1df0d4abe78bbca68fb085a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/78c3bbeaeb266aac1df0d4abe78bbca68fb085a8
new file mode 100644
index 0000000..560f4fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/78c3bbeaeb266aac1df0d4abe78bbca68fb085a8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7957953ca449974ec39c6a137c0acdedb71c3b02 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7957953ca449974ec39c6a137c0acdedb71c3b02
new file mode 100644
index 0000000..65bba5a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7957953ca449974ec39c6a137c0acdedb71c3b02
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/798fd96821ee3d91952373024f35cdceb10ccbed b/test/core/end2end/fuzzers/api_fuzzer_corpus/798fd96821ee3d91952373024f35cdceb10ccbed
new file mode 100644
index 0000000..c33e5f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/798fd96821ee3d91952373024f35cdceb10ccbed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/79ac297c667d2ae77c05d2af275b05138439ee5b b/test/core/end2end/fuzzers/api_fuzzer_corpus/79ac297c667d2ae77c05d2af275b05138439ee5b
new file mode 100644
index 0000000..06baaa7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/79ac297c667d2ae77c05d2af275b05138439ee5b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7b4b493ac5a36d3b3fed0b66bc504206548a3537 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b4b493ac5a36d3b3fed0b66bc504206548a3537
new file mode 100644
index 0000000..a27ffd3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b4b493ac5a36d3b3fed0b66bc504206548a3537
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7bb25e1821f1ff6ea4c85259444f7f40b430aa1f b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bb25e1821f1ff6ea4c85259444f7f40b430aa1f
new file mode 100644
index 0000000..35c5a9d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bb25e1821f1ff6ea4c85259444f7f40b430aa1f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7bd75ddceb75724e5e9205cf7fadec03d8e1aca2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bd75ddceb75724e5e9205cf7fadec03d8e1aca2
new file mode 100644
index 0000000..1a610e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bd75ddceb75724e5e9205cf7fadec03d8e1aca2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7bdc25dc79ca942673e515126e22474fd89ce55e b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bdc25dc79ca942673e515126e22474fd89ce55e
new file mode 100644
index 0000000..8d9dd1f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bdc25dc79ca942673e515126e22474fd89ce55e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7bf8d2b77d85e4042e47d0dbe6da9441c6d9530b b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bf8d2b77d85e4042e47d0dbe6da9441c6d9530b
new file mode 100644
index 0000000..eaf8a8f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7bf8d2b77d85e4042e47d0dbe6da9441c6d9530b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c193442a422da21cdeb14f681b0d4179aaeaf5f b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c193442a422da21cdeb14f681b0d4179aaeaf5f
new file mode 100644
index 0000000..a1fdbfd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c193442a422da21cdeb14f681b0d4179aaeaf5f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c6a381eac8fbc8fccada2b2069c3f773a9c6961 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c6a381eac8fbc8fccada2b2069c3f773a9c6961
new file mode 100644
index 0000000..33d9878
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c6a381eac8fbc8fccada2b2069c3f773a9c6961
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7c70dd584df7a4fda61d08ab8ef85ec70c85b7f5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c70dd584df7a4fda61d08ab8ef85ec70c85b7f5
new file mode 100644
index 0000000..39f933f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7c70dd584df7a4fda61d08ab8ef85ec70c85b7f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7cc958be492e942df2b784fcc08a63d57c7fef92 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cc958be492e942df2b784fcc08a63d57c7fef92
new file mode 100644
index 0000000..a405612
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cc958be492e942df2b784fcc08a63d57c7fef92
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7d8eeb8778051e621abf74daf43dd4010117d9f9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d8eeb8778051e621abf74daf43dd4010117d9f9
new file mode 100644
index 0000000..1e6d894
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d8eeb8778051e621abf74daf43dd4010117d9f9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7e29172a1d27c4f8a0b138306db1043373b2d0ba b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e29172a1d27c4f8a0b138306db1043373b2d0ba
new file mode 100644
index 0000000..65c18d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e29172a1d27c4f8a0b138306db1043373b2d0ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7ec62c16916c2c30847b578d2148893924287bfe b/test/core/end2end/fuzzers/api_fuzzer_corpus/7ec62c16916c2c30847b578d2148893924287bfe
new file mode 100644
index 0000000..a326d20
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7ec62c16916c2c30847b578d2148893924287bfe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7eea6a4b31c4f10281f31a7461f35af7331becf2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7eea6a4b31c4f10281f31a7461f35af7331becf2
new file mode 100644
index 0000000..86ca443
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7eea6a4b31c4f10281f31a7461f35af7331becf2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7efac665d3dabc2162f4407e3bedbd65b3007335 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7efac665d3dabc2162f4407e3bedbd65b3007335
new file mode 100644
index 0000000..aa8d8c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7efac665d3dabc2162f4407e3bedbd65b3007335
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7fe7a6ab57422c40c7e0e2333c3bbb6ae6a0d9a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7fe7a6ab57422c40c7e0e2333c3bbb6ae6a0d9a3
new file mode 100644
index 0000000..00ff25a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7fe7a6ab57422c40c7e0e2333c3bbb6ae6a0d9a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/80ecd5087801e974eae7db730a496d2aca110648 b/test/core/end2end/fuzzers/api_fuzzer_corpus/80ecd5087801e974eae7db730a496d2aca110648
new file mode 100644
index 0000000..0d16b9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/80ecd5087801e974eae7db730a496d2aca110648
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/81489a0c6a71c48e9f343cb5ff8e8b5693d5df19 b/test/core/end2end/fuzzers/api_fuzzer_corpus/81489a0c6a71c48e9f343cb5ff8e8b5693d5df19
new file mode 100644
index 0000000..5fab90d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/81489a0c6a71c48e9f343cb5ff8e8b5693d5df19
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/819cac3befd0d7b12ffd734c26df1cdf43c376a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/819cac3befd0d7b12ffd734c26df1cdf43c376a2
new file mode 100644
index 0000000..01c0445
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/819cac3befd0d7b12ffd734c26df1cdf43c376a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/81e64ec00272538edef6336423738277647b5ed0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/81e64ec00272538edef6336423738277647b5ed0
new file mode 100644
index 0000000..69dd622
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/81e64ec00272538edef6336423738277647b5ed0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/82182d7a9c73a70f5eec58c03b1db511d7feb95d b/test/core/end2end/fuzzers/api_fuzzer_corpus/82182d7a9c73a70f5eec58c03b1db511d7feb95d
new file mode 100644
index 0000000..6b61294
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/82182d7a9c73a70f5eec58c03b1db511d7feb95d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a b/test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a
new file mode 100644
index 0000000..3b711c3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/840928fe62714fdb003b3f0a40c2c4897f9d7938 b/test/core/end2end/fuzzers/api_fuzzer_corpus/840928fe62714fdb003b3f0a40c2c4897f9d7938
new file mode 100644
index 0000000..9518177
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/840928fe62714fdb003b3f0a40c2c4897f9d7938
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/84650393df0dca7ca3244faa7ac036873d3dcce1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/84650393df0dca7ca3244faa7ac036873d3dcce1
new file mode 100644
index 0000000..6ac2f60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/84650393df0dca7ca3244faa7ac036873d3dcce1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/85bd45792a3cf2116fab5e99e2d824ee804af843 b/test/core/end2end/fuzzers/api_fuzzer_corpus/85bd45792a3cf2116fab5e99e2d824ee804af843
new file mode 100644
index 0000000..eec85e6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/85bd45792a3cf2116fab5e99e2d824ee804af843
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/875280c0c54d1662b07150e728f9ac0c1af7bf66 b/test/core/end2end/fuzzers/api_fuzzer_corpus/875280c0c54d1662b07150e728f9ac0c1af7bf66
new file mode 100644
index 0000000..76a53d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/875280c0c54d1662b07150e728f9ac0c1af7bf66
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87e510c4dd906ec4de0066e93b2475480fc0768b b/test/core/end2end/fuzzers/api_fuzzer_corpus/87e510c4dd906ec4de0066e93b2475480fc0768b
new file mode 100644
index 0000000..cdc769a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/87e510c4dd906ec4de0066e93b2475480fc0768b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/88139a0d01f144556ef861af4450f466081443f5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/88139a0d01f144556ef861af4450f466081443f5
new file mode 100644
index 0000000..7b242bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/88139a0d01f144556ef861af4450f466081443f5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8854a331f3c5ddc4ace70e0505901e53aa48e386 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8854a331f3c5ddc4ace70e0505901e53aa48e386
new file mode 100644
index 0000000..feba4eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8854a331f3c5ddc4ace70e0505901e53aa48e386
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/88600f27cb602db290f07eb0e8b6f10488c0760f b/test/core/end2end/fuzzers/api_fuzzer_corpus/88600f27cb602db290f07eb0e8b6f10488c0760f
new file mode 100644
index 0000000..56be62d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/88600f27cb602db290f07eb0e8b6f10488c0760f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8979c4017b72b970dc33095be26788f52f37a959 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8979c4017b72b970dc33095be26788f52f37a959
new file mode 100644
index 0000000..64fd265
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8979c4017b72b970dc33095be26788f52f37a959
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7
new file mode 100644
index 0000000..47d943f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8aaa277cf855a972c6dec9fc49b171ce3232a26a b/test/core/end2end/fuzzers/api_fuzzer_corpus/8aaa277cf855a972c6dec9fc49b171ce3232a26a
new file mode 100644
index 0000000..38a319b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8aaa277cf855a972c6dec9fc49b171ce3232a26a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ab19633328ea9e493dee313e135e7d851aa7911 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ab19633328ea9e493dee313e135e7d851aa7911
new file mode 100644
index 0000000..24b8e2d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ab19633328ea9e493dee313e135e7d851aa7911
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b30c1f058ac421b6c51c4591ef9e4adc2886b44 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b30c1f058ac421b6c51c4591ef9e4adc2886b44
new file mode 100644
index 0000000..ca577c4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b30c1f058ac421b6c51c4591ef9e4adc2886b44
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b37ce939cb8d42c459f5e286de980c7b62f14be b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b37ce939cb8d42c459f5e286de980c7b62f14be
new file mode 100644
index 0000000..cf06afd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b37ce939cb8d42c459f5e286de980c7b62f14be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ba87aeecf944e0eb387f8f2d9e30964c9f860de b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ba87aeecf944e0eb387f8f2d9e30964c9f860de
new file mode 100644
index 0000000..cd7f1ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ba87aeecf944e0eb387f8f2d9e30964c9f860de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8bd94413e2d60effc2806dd7153216a1b6487162 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8bd94413e2d60effc2806dd7153216a1b6487162
new file mode 100644
index 0000000..9e12664
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8bd94413e2d60effc2806dd7153216a1b6487162
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681
new file mode 100644
index 0000000..6eae9d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c540353717db453eeb865e5b9b7f2efe6c5d5b7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c540353717db453eeb865e5b9b7f2efe6c5d5b7
new file mode 100644
index 0000000..1f97037
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c540353717db453eeb865e5b9b7f2efe6c5d5b7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8d386a409662ef68370c0c552742bd0ea6d527d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d386a409662ef68370c0c552742bd0ea6d527d5
new file mode 100644
index 0000000..e987d01
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d386a409662ef68370c0c552742bd0ea6d527d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8d91dd322c7972a13cb98461b0eb284116905887 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d91dd322c7972a13cb98461b0eb284116905887
new file mode 100644
index 0000000..41a1408
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d91dd322c7972a13cb98461b0eb284116905887
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8dab1d2d4f470c669688103f52718a7783113cf1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dab1d2d4f470c669688103f52718a7783113cf1
new file mode 100644
index 0000000..6a75add
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dab1d2d4f470c669688103f52718a7783113cf1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8dcb4dd3d2fa04ffc83f7fd7f9306ae4105ef7ef b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dcb4dd3d2fa04ffc83f7fd7f9306ae4105ef7ef
new file mode 100644
index 0000000..5015551
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dcb4dd3d2fa04ffc83f7fd7f9306ae4105ef7ef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ebddbd256887fb5fe1be69a46023b34f815d2e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ebddbd256887fb5fe1be69a46023b34f815d2e8
new file mode 100644
index 0000000..fd167a5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ebddbd256887fb5fe1be69a46023b34f815d2e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8edad87970b31dad2b23184d864fe5ad9efb05e5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8edad87970b31dad2b23184d864fe5ad9efb05e5
new file mode 100644
index 0000000..06337c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8edad87970b31dad2b23184d864fe5ad9efb05e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f4187ea7f2efbcd933fdb2b0652b71ecaff7822 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f4187ea7f2efbcd933fdb2b0652b71ecaff7822
new file mode 100644
index 0000000..66c4cbf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f4187ea7f2efbcd933fdb2b0652b71ecaff7822
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3
new file mode 100644
index 0000000..29b8e4a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805
new file mode 100644
index 0000000..a4f0ce8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92ec3b6722dde442121b3d1ed3ef23976c72cba8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92ec3b6722dde442121b3d1ed3ef23976c72cba8
new file mode 100644
index 0000000..08e2196
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92ec3b6722dde442121b3d1ed3ef23976c72cba8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/940a622e8995529f6b0455906d8a035902682d2d b/test/core/end2end/fuzzers/api_fuzzer_corpus/940a622e8995529f6b0455906d8a035902682d2d
new file mode 100644
index 0000000..39dbccf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/940a622e8995529f6b0455906d8a035902682d2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/940e35bed3ff2b52a29e5b15acf9fe39772eb5de b/test/core/end2end/fuzzers/api_fuzzer_corpus/940e35bed3ff2b52a29e5b15acf9fe39772eb5de
new file mode 100644
index 0000000..3a7c9ab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/940e35bed3ff2b52a29e5b15acf9fe39772eb5de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/94571a4b13c435117ef9bd914443ce9a07da8e3f b/test/core/end2end/fuzzers/api_fuzzer_corpus/94571a4b13c435117ef9bd914443ce9a07da8e3f
new file mode 100644
index 0000000..87cf504
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/94571a4b13c435117ef9bd914443ce9a07da8e3f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/95940316e7104e9c2d5123b31e36b2dfd12fcea2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/95940316e7104e9c2d5123b31e36b2dfd12fcea2
new file mode 100644
index 0000000..380dc5e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/95940316e7104e9c2d5123b31e36b2dfd12fcea2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/95dd85860bde08e1d0ecef805ad55f66008923af b/test/core/end2end/fuzzers/api_fuzzer_corpus/95dd85860bde08e1d0ecef805ad55f66008923af
new file mode 100644
index 0000000..f04672b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/95dd85860bde08e1d0ecef805ad55f66008923af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/95f223f8964d294aafc2a6041a83cfa7761c31ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/95f223f8964d294aafc2a6041a83cfa7761c31ab
new file mode 100644
index 0000000..3752f87
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/95f223f8964d294aafc2a6041a83cfa7761c31ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c00d91e6146b29f7559a944e6bf8dce7d0f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c00d91e6146b29f7559a944e6bf8dce7d0f1
new file mode 100644
index 0000000..ddec411
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9629c00d91e6146b29f7559a944e6bf8dce7d0f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/96a6293d4fc97c75f037bdb0f73dc5b62bbfa2e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/96a6293d4fc97c75f037bdb0f73dc5b62bbfa2e6
new file mode 100644
index 0000000..5e370d3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/96a6293d4fc97c75f037bdb0f73dc5b62bbfa2e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97011f865fcf9c57560d5ed3cb05883ff298ee35 b/test/core/end2end/fuzzers/api_fuzzer_corpus/97011f865fcf9c57560d5ed3cb05883ff298ee35
new file mode 100644
index 0000000..fff5097
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97011f865fcf9c57560d5ed3cb05883ff298ee35
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97440beca022cd5799f76654d8bec51f62c0bbaf b/test/core/end2end/fuzzers/api_fuzzer_corpus/97440beca022cd5799f76654d8bec51f62c0bbaf
new file mode 100644
index 0000000..15c9411
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97440beca022cd5799f76654d8bec51f62c0bbaf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/976613cb09127a752d628c4a3cf73b8e3168e0af b/test/core/end2end/fuzzers/api_fuzzer_corpus/976613cb09127a752d628c4a3cf73b8e3168e0af
new file mode 100644
index 0000000..a35a8db
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/976613cb09127a752d628c4a3cf73b8e3168e0af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97817475213736527fdc3b2a28cd45f52fe4ce1a b/test/core/end2end/fuzzers/api_fuzzer_corpus/97817475213736527fdc3b2a28cd45f52fe4ce1a
new file mode 100644
index 0000000..23a7584
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97817475213736527fdc3b2a28cd45f52fe4ce1a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97efcb1f37032ebf01b4b1065a9df66590b7051f b/test/core/end2end/fuzzers/api_fuzzer_corpus/97efcb1f37032ebf01b4b1065a9df66590b7051f
new file mode 100644
index 0000000..d76ab52
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97efcb1f37032ebf01b4b1065a9df66590b7051f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/980f0198dc66e867b1a5d04cf24bc02fbdf3b839 b/test/core/end2end/fuzzers/api_fuzzer_corpus/980f0198dc66e867b1a5d04cf24bc02fbdf3b839
new file mode 100644
index 0000000..4782ad9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/980f0198dc66e867b1a5d04cf24bc02fbdf3b839
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98569dc166bfcfef45a66db4de1c0f34340c269c b/test/core/end2end/fuzzers/api_fuzzer_corpus/98569dc166bfcfef45a66db4de1c0f34340c269c
new file mode 100644
index 0000000..51fa365
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/98569dc166bfcfef45a66db4de1c0f34340c269c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/988bd333d5dabe1561cf4429e7481ff110be0da4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/988bd333d5dabe1561cf4429e7481ff110be0da4
new file mode 100644
index 0000000..948abb1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/988bd333d5dabe1561cf4429e7481ff110be0da4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98cdb5ba5725c6b2ed39fc514401fe987fc2d9af b/test/core/end2end/fuzzers/api_fuzzer_corpus/98cdb5ba5725c6b2ed39fc514401fe987fc2d9af
new file mode 100644
index 0000000..c858bae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/98cdb5ba5725c6b2ed39fc514401fe987fc2d9af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9989534524a212092e9d7fede16106b586c434f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9989534524a212092e9d7fede16106b586c434f4
new file mode 100644
index 0000000..f38f1bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9989534524a212092e9d7fede16106b586c434f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/999737edf1e9740df084c4326ec983137ccd7111 b/test/core/end2end/fuzzers/api_fuzzer_corpus/999737edf1e9740df084c4326ec983137ccd7111
new file mode 100644
index 0000000..38c8381
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/999737edf1e9740df084c4326ec983137ccd7111
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/99e8f2ea80ed1d5a78fd5236e89d404bb0c03940 b/test/core/end2end/fuzzers/api_fuzzer_corpus/99e8f2ea80ed1d5a78fd5236e89d404bb0c03940
new file mode 100644
index 0000000..7eb66b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/99e8f2ea80ed1d5a78fd5236e89d404bb0c03940
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0f0818ff9fbfd81e0d0eadeef7b85ca2d4fd46 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0f0818ff9fbfd81e0d0eadeef7b85ca2d4fd46
new file mode 100644
index 0000000..98ff843
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a0f0818ff9fbfd81e0d0eadeef7b85ca2d4fd46
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9a9af9f266737f95cfedbf5c8fcea22660c3f085 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a9af9f266737f95cfedbf5c8fcea22660c3f085
new file mode 100644
index 0000000..40bd95c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9a9af9f266737f95cfedbf5c8fcea22660c3f085
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9ab3be55bd49749439f7aa1bfe2d178ad663b003 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ab3be55bd49749439f7aa1bfe2d178ad663b003
new file mode 100644
index 0000000..d5e4ff6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ab3be55bd49749439f7aa1bfe2d178ad663b003
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9addda4c7a9940fbbda2218ec58560c10e1df9f7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9addda4c7a9940fbbda2218ec58560c10e1df9f7
new file mode 100644
index 0000000..0a6e751
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9addda4c7a9940fbbda2218ec58560c10e1df9f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9b5b436057dfcf4299e52ad49c74e45ef04be7a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b5b436057dfcf4299e52ad49c74e45ef04be7a2
new file mode 100644
index 0000000..07c01de
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b5b436057dfcf4299e52ad49c74e45ef04be7a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9cb91ce75745cc30995b8985a35ea31db766e54c b/test/core/end2end/fuzzers/api_fuzzer_corpus/9cb91ce75745cc30995b8985a35ea31db766e54c
new file mode 100644
index 0000000..9c6f308
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9cb91ce75745cc30995b8985a35ea31db766e54c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d004fd9a35647ba7ec169e6fedbf9dce5f9623f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d004fd9a35647ba7ec169e6fedbf9dce5f9623f
new file mode 100644
index 0000000..e67ab1d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d004fd9a35647ba7ec169e6fedbf9dce5f9623f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d69b6fb15c861c294878da8aaf16a531dfb1b70 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d69b6fb15c861c294878da8aaf16a531dfb1b70
new file mode 100644
index 0000000..e7dac59
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d69b6fb15c861c294878da8aaf16a531dfb1b70
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d74922516d210da71d40395f17a3cef4161894d b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d74922516d210da71d40395f17a3cef4161894d
new file mode 100644
index 0000000..5496b7d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d74922516d210da71d40395f17a3cef4161894d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd25a6857d92ef52169ec95a0cdfbc8570b6d99 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd25a6857d92ef52169ec95a0cdfbc8570b6d99
new file mode 100644
index 0000000..cd272b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd25a6857d92ef52169ec95a0cdfbc8570b6d99
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf b/test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf
new file mode 100644
index 0000000..b7dec16
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f00c8665f3918e666d424ee67a2556f2651d64f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f00c8665f3918e666d424ee67a2556f2651d64f
new file mode 100644
index 0000000..2b0bef7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f00c8665f3918e666d424ee67a2556f2651d64f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f43969c0777a021539b59eafdac9dd2f51422d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f43969c0777a021539b59eafdac9dd2f51422d5
new file mode 100644
index 0000000..e059802
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f43969c0777a021539b59eafdac9dd2f51422d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f643e51d8e91e7e0348017d98078f078a1790b9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f643e51d8e91e7e0348017d98078f078a1790b9
new file mode 100644
index 0000000..410ba75
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f643e51d8e91e7e0348017d98078f078a1790b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f86fc902ca36482d09f6c11e821b79bfc0b98cc b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f86fc902ca36482d09f6c11e821b79bfc0b98cc
new file mode 100644
index 0000000..36a2080
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f86fc902ca36482d09f6c11e821b79bfc0b98cc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a0e80579e201495c2337292a3508b2d220e9737a b/test/core/end2end/fuzzers/api_fuzzer_corpus/a0e80579e201495c2337292a3508b2d220e9737a
new file mode 100644
index 0000000..296cee3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a0e80579e201495c2337292a3508b2d220e9737a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a18ed3861270cd42a661211d9d970c488fed46ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/a18ed3861270cd42a661211d9d970c488fed46ad
new file mode 100644
index 0000000..4b765b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a18ed3861270cd42a661211d9d970c488fed46ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f6961a480f1eb49b394118b05b9cdabfb6f0a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f6961a480f1eb49b394118b05b9cdabfb6f0a3
new file mode 100644
index 0000000..4576144
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f6961a480f1eb49b394118b05b9cdabfb6f0a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a156c5ed8a55aec450393deaed66c0e9117c9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a156c5ed8a55aec450393deaed66c0e9117c9
new file mode 100644
index 0000000..cf7b2b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a156c5ed8a55aec450393deaed66c0e9117c9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a380f7e56171dc69269afb6364216bc69925eb8a b/test/core/end2end/fuzzers/api_fuzzer_corpus/a380f7e56171dc69269afb6364216bc69925eb8a
new file mode 100644
index 0000000..048036e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a380f7e56171dc69269afb6364216bc69925eb8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3926a25374714a71c8bd515564d294df229c7cf b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3926a25374714a71c8bd515564d294df229c7cf
new file mode 100644
index 0000000..b13e050
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3926a25374714a71c8bd515564d294df229c7cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3d52dfd05da328d3f109d125e6c1a15470eab06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3d52dfd05da328d3f109d125e6c1a15470eab06
new file mode 100644
index 0000000..d9bc8d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3d52dfd05da328d3f109d125e6c1a15470eab06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a41e8b175a837b55e540874c3f056a9d9535866c b/test/core/end2end/fuzzers/api_fuzzer_corpus/a41e8b175a837b55e540874c3f056a9d9535866c
new file mode 100644
index 0000000..b472beb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a41e8b175a837b55e540874c3f056a9d9535866c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a4d41bf7bce38a255a431912f6b57637645221e8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a4d41bf7bce38a255a431912f6b57637645221e8
new file mode 100644
index 0000000..b39f02d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a4d41bf7bce38a255a431912f6b57637645221e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a619bb6ff4871fab3045e46bef8036f80d605f37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a619bb6ff4871fab3045e46bef8036f80d605f37
new file mode 100644
index 0000000..3054cdb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a619bb6ff4871fab3045e46bef8036f80d605f37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a62960425c597cf5d2bd38e9412363991479837f b/test/core/end2end/fuzzers/api_fuzzer_corpus/a62960425c597cf5d2bd38e9412363991479837f
new file mode 100644
index 0000000..109cf04
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a62960425c597cf5d2bd38e9412363991479837f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a64136997cd4c4be7d93f10fd6a1d12cdc22691c b/test/core/end2end/fuzzers/api_fuzzer_corpus/a64136997cd4c4be7d93f10fd6a1d12cdc22691c
new file mode 100644
index 0000000..145b962
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a64136997cd4c4be7d93f10fd6a1d12cdc22691c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a6541e0f317553947d53cfb9318367aff2898ad5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6541e0f317553947d53cfb9318367aff2898ad5
new file mode 100644
index 0000000..7893d71
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6541e0f317553947d53cfb9318367aff2898ad5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a8115b0be87517139447c9fefc33e225f2efdf32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8115b0be87517139447c9fefc33e225f2efdf32
new file mode 100644
index 0000000..010d0c4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8115b0be87517139447c9fefc33e225f2efdf32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315
new file mode 100644
index 0000000..39a8d85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abaca8e8237d5add7e35752471688233d265efc2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/abaca8e8237d5add7e35752471688233d265efc2
new file mode 100644
index 0000000..fbfa420
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abaca8e8237d5add7e35752471688233d265efc2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abbd9f85ad500d55dda6009681ddffca1849b632 b/test/core/end2end/fuzzers/api_fuzzer_corpus/abbd9f85ad500d55dda6009681ddffca1849b632
new file mode 100644
index 0000000..0cec8e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abbd9f85ad500d55dda6009681ddffca1849b632
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abcfa029d3eb7c016a162e78e7351f64b9905a42 b/test/core/end2end/fuzzers/api_fuzzer_corpus/abcfa029d3eb7c016a162e78e7351f64b9905a42
new file mode 100644
index 0000000..6f8f8fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abcfa029d3eb7c016a162e78e7351f64b9905a42
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abdb7891569085e3df0f6c7a5348c12bf3dd1ae0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/abdb7891569085e3df0f6c7a5348c12bf3dd1ae0
new file mode 100644
index 0000000..09803b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abdb7891569085e3df0f6c7a5348c12bf3dd1ae0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ad6369d2c51c4787778ff9dbd86cc6df44312f1d b/test/core/end2end/fuzzers/api_fuzzer_corpus/ad6369d2c51c4787778ff9dbd86cc6df44312f1d
new file mode 100644
index 0000000..2b28c68
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ad6369d2c51c4787778ff9dbd86cc6df44312f1d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ada998a4b5a9895f514ddbf8da775f5c59736021 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ada998a4b5a9895f514ddbf8da775f5c59736021
new file mode 100644
index 0000000..287ac9b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ada998a4b5a9895f514ddbf8da775f5c59736021
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/af1fbe820d92608782360791113393055c171da0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/af1fbe820d92608782360791113393055c171da0
new file mode 100644
index 0000000..ba0b354
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/af1fbe820d92608782360791113393055c171da0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/af990e5c81c307c188a79f4cdfdae4e8e15dc4a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/af990e5c81c307c188a79f4cdfdae4e8e15dc4a2
new file mode 100644
index 0000000..1f41e50
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/af990e5c81c307c188a79f4cdfdae4e8e15dc4a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aff1fdfe79c104bce110cec92e1e021caf012fde b/test/core/end2end/fuzzers/api_fuzzer_corpus/aff1fdfe79c104bce110cec92e1e021caf012fde
new file mode 100644
index 0000000..23e87ea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aff1fdfe79c104bce110cec92e1e021caf012fde
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b2432248370f7590e894c54f2dd13fe9df9fa53e b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2432248370f7590e894c54f2dd13fe9df9fa53e
new file mode 100644
index 0000000..304a279
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2432248370f7590e894c54f2dd13fe9df9fa53e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b262c677b8c46262f1fc4982f5abf4ef603abe1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/b262c677b8c46262f1fc4982f5abf4ef603abe1c
new file mode 100644
index 0000000..b859d32
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b262c677b8c46262f1fc4982f5abf4ef603abe1c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b2af0db70de3a6ddcb188d1f6f2a673133a8f9c7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2af0db70de3a6ddcb188d1f6f2a673133a8f9c7
new file mode 100644
index 0000000..e0421d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2af0db70de3a6ddcb188d1f6f2a673133a8f9c7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b2f450dc86671548200a1fe6ee0ee76171edc578 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2f450dc86671548200a1fe6ee0ee76171edc578
new file mode 100644
index 0000000..6995281
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2f450dc86671548200a1fe6ee0ee76171edc578
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b35f51d95f597075bb93cd9d2135870fe0a73486 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b35f51d95f597075bb93cd9d2135870fe0a73486
new file mode 100644
index 0000000..7c7d787
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b35f51d95f597075bb93cd9d2135870fe0a73486
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b37ab56aacf7fea7dcade26810117c45e6041068 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b37ab56aacf7fea7dcade26810117c45e6041068
new file mode 100644
index 0000000..af1bd2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b37ab56aacf7fea7dcade26810117c45e6041068
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b5bec1a19e2ca2394f2c3235266c22a7167bfa5d b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5bec1a19e2ca2394f2c3235266c22a7167bfa5d
new file mode 100644
index 0000000..ac5fd19
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5bec1a19e2ca2394f2c3235266c22a7167bfa5d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b5dfbf1965f794634249cc6be9d20d2a9fc6e332 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5dfbf1965f794634249cc6be9d20d2a9fc6e332
new file mode 100644
index 0000000..9cd4033
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b5dfbf1965f794634249cc6be9d20d2a9fc6e332
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b6694ec2d425e8ce6ad9ff712a999fabfa5ce113 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6694ec2d425e8ce6ad9ff712a999fabfa5ce113
new file mode 100644
index 0000000..b28d370
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6694ec2d425e8ce6ad9ff712a999fabfa5ce113
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b6c47632d8d697f9f2923bde053f7a5571150705 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6c47632d8d697f9f2923bde053f7a5571150705
new file mode 100644
index 0000000..e2db125
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6c47632d8d697f9f2923bde053f7a5571150705
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b892c064b2703ac0dc31766946be487b197a541e b/test/core/end2end/fuzzers/api_fuzzer_corpus/b892c064b2703ac0dc31766946be487b197a541e
new file mode 100644
index 0000000..5404a04
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b892c064b2703ac0dc31766946be487b197a541e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8d0be707d9505c0e63253904979492c22cd9fdc b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8d0be707d9505c0e63253904979492c22cd9fdc
new file mode 100644
index 0000000..6792e9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8d0be707d9505c0e63253904979492c22cd9fdc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8e06536840e31a343b3a42b677d623bacfccd99 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8e06536840e31a343b3a42b677d623bacfccd99
new file mode 100644
index 0000000..77a3b9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8e06536840e31a343b3a42b677d623bacfccd99
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8ea2247c5b1636148fa66fdce22ed1cc72b6bdd b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8ea2247c5b1636148fa66fdce22ed1cc72b6bdd
new file mode 100644
index 0000000..8a34fd2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8ea2247c5b1636148fa66fdce22ed1cc72b6bdd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b9318513eb6b1db553855cd062ebbd4d1db9b846 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9318513eb6b1db553855cd062ebbd4d1db9b846
new file mode 100644
index 0000000..d3dfb9a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9318513eb6b1db553855cd062ebbd4d1db9b846
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b95899d40afc4b3ff87af2285b61ba66939873fa b/test/core/end2end/fuzzers/api_fuzzer_corpus/b95899d40afc4b3ff87af2285b61ba66939873fa
new file mode 100644
index 0000000..2666199
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b95899d40afc4b3ff87af2285b61ba66939873fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b98ef7107754379c22a3ad59cffa3183e0804c0e b/test/core/end2end/fuzzers/api_fuzzer_corpus/b98ef7107754379c22a3ad59cffa3183e0804c0e
new file mode 100644
index 0000000..4bff61b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b98ef7107754379c22a3ad59cffa3183e0804c0e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b9913b354096dbe1796814e2cea80addef6ee386 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9913b354096dbe1796814e2cea80addef6ee386
new file mode 100644
index 0000000..2133d9d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9913b354096dbe1796814e2cea80addef6ee386
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ba3d174125e7378292fcbad9bfe8129dabf88b3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ba3d174125e7378292fcbad9bfe8129dabf88b3a
new file mode 100644
index 0000000..8600bd5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ba3d174125e7378292fcbad9bfe8129dabf88b3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/baab31938837e1a3cb49ca12fb886fcbb7d48501 b/test/core/end2end/fuzzers/api_fuzzer_corpus/baab31938837e1a3cb49ca12fb886fcbb7d48501
new file mode 100644
index 0000000..6c7b604
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/baab31938837e1a3cb49ca12fb886fcbb7d48501
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bac43cd2ed1dbf3a89a0c66d8983b586066ef463 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bac43cd2ed1dbf3a89a0c66d8983b586066ef463
new file mode 100644
index 0000000..61feecd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bac43cd2ed1dbf3a89a0c66d8983b586066ef463
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bb2affdc830241ebea35795fed3bc8d478330eec b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb2affdc830241ebea35795fed3bc8d478330eec
new file mode 100644
index 0000000..c97b75e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb2affdc830241ebea35795fed3bc8d478330eec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bb54fde05891ecc235263ad087cfd9682a25f76d b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb54fde05891ecc235263ad087cfd9682a25f76d
new file mode 100644
index 0000000..7b31d32
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb54fde05891ecc235263ad087cfd9682a25f76d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bba4073cde10ba7abaac18d6303e310d02a47826 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bba4073cde10ba7abaac18d6303e310d02a47826
new file mode 100644
index 0000000..e73c25b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bba4073cde10ba7abaac18d6303e310d02a47826
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc2967ecf8402d442ef63ca451497431932a7e57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc2967ecf8402d442ef63ca451497431932a7e57
new file mode 100644
index 0000000..99ee098
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc2967ecf8402d442ef63ca451497431932a7e57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc8dd89f31fa5e89cabace6d7701d2a218f97aed b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc8dd89f31fa5e89cabace6d7701d2a218f97aed
new file mode 100644
index 0000000..4c45a33
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc8dd89f31fa5e89cabace6d7701d2a218f97aed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd04c9dc7eaf030313d4c87f190a9d973b96ac2d b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd04c9dc7eaf030313d4c87f190a9d973b96ac2d
new file mode 100644
index 0000000..d1d5a78
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd04c9dc7eaf030313d4c87f190a9d973b96ac2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd585e031f586c4313c6b00e5f247f6b272ce902 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd585e031f586c4313c6b00e5f247f6b272ce902
new file mode 100644
index 0000000..5223bb0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd585e031f586c4313c6b00e5f247f6b272ce902
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bdab9cab03ad7aa611612e02775018112303d3cd b/test/core/end2end/fuzzers/api_fuzzer_corpus/bdab9cab03ad7aa611612e02775018112303d3cd
new file mode 100644
index 0000000..e5e20af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bdab9cab03ad7aa611612e02775018112303d3cd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/be29c4d0b6568b06c69fc339ac29890baac569de b/test/core/end2end/fuzzers/api_fuzzer_corpus/be29c4d0b6568b06c69fc339ac29890baac569de
new file mode 100644
index 0000000..d45f253
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/be29c4d0b6568b06c69fc339ac29890baac569de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/be757e0ca581bb4ec14fbba6e87569f93f4c7750 b/test/core/end2end/fuzzers/api_fuzzer_corpus/be757e0ca581bb4ec14fbba6e87569f93f4c7750
new file mode 100644
index 0000000..31dde29
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/be757e0ca581bb4ec14fbba6e87569f93f4c7750
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/be8114a7bd73ce15fe0495171234d0af526e41f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/be8114a7bd73ce15fe0495171234d0af526e41f1
new file mode 100644
index 0000000..b770bb7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/be8114a7bd73ce15fe0495171234d0af526e41f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/becdf72b57104cede4a1fc7b7a4c97a3cbf3b7b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/becdf72b57104cede4a1fc7b7a4c97a3cbf3b7b4
new file mode 100644
index 0000000..a33af53
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/becdf72b57104cede4a1fc7b7a4c97a3cbf3b7b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/beff7e2d09ef0547a3b1a498311c665954d8baea b/test/core/end2end/fuzzers/api_fuzzer_corpus/beff7e2d09ef0547a3b1a498311c665954d8baea
new file mode 100644
index 0000000..36b5ce9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/beff7e2d09ef0547a3b1a498311c665954d8baea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005
new file mode 100644
index 0000000..fc2c6bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c061aa42448363b548d90cbf4a7660fb2b043518 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c061aa42448363b548d90cbf4a7660fb2b043518
new file mode 100644
index 0000000..958bbd5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c061aa42448363b548d90cbf4a7660fb2b043518
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c0bb5f00fc14ea4f2000f75e6d1d94f23e6203f6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c0bb5f00fc14ea4f2000f75e6d1d94f23e6203f6
new file mode 100644
index 0000000..952d8ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c0bb5f00fc14ea4f2000f75e6d1d94f23e6203f6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c0e04f5709338a500b3be166714ed7b0013c17d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c0e04f5709338a500b3be166714ed7b0013c17d0
new file mode 100644
index 0000000..556fb44
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c0e04f5709338a500b3be166714ed7b0013c17d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c11e6f232cfdc5fffffa2c79150b5647704912c0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c11e6f232cfdc5fffffa2c79150b5647704912c0
new file mode 100644
index 0000000..2161194
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c11e6f232cfdc5fffffa2c79150b5647704912c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c16876cdc8ab36ef7083bf4579849ee94239af0f b/test/core/end2end/fuzzers/api_fuzzer_corpus/c16876cdc8ab36ef7083bf4579849ee94239af0f
new file mode 100644
index 0000000..4146d6f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c16876cdc8ab36ef7083bf4579849ee94239af0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c1ac67facfa4ca5ad92c3eed576a59d41558480f b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1ac67facfa4ca5ad92c3eed576a59d41558480f
new file mode 100644
index 0000000..71934fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1ac67facfa4ca5ad92c3eed576a59d41558480f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d33a370a8ec2c2ea380472cc49172c679fa5bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d33a370a8ec2c2ea380472cc49172c679fa5bc
new file mode 100644
index 0000000..8449ca5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d33a370a8ec2c2ea380472cc49172c679fa5bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d84db44208d08a84084986094aeac3eebfe3b8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d84db44208d08a84084986094aeac3eebfe3b8
new file mode 100644
index 0000000..81e421b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1d84db44208d08a84084986094aeac3eebfe3b8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c259fba0af17dd1636501feddd52e501b51c4137 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c259fba0af17dd1636501feddd52e501b51c4137
new file mode 100644
index 0000000..4d0b6c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c259fba0af17dd1636501feddd52e501b51c4137
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f63aa5c4462b359c9028b6e6031dc088d7d46 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f63aa5c4462b359c9028b6e6031dc088d7d46
new file mode 100644
index 0000000..2f4522a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f63aa5c4462b359c9028b6e6031dc088d7d46
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c2eb3287f8b83c9281826e3c773ca347056ee115 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c2eb3287f8b83c9281826e3c773ca347056ee115
new file mode 100644
index 0000000..24a6990
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c2eb3287f8b83c9281826e3c773ca347056ee115
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c32029d5683ad5cfa1af3b534c53bc2f7f513f50 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c32029d5683ad5cfa1af3b534c53bc2f7f513f50
new file mode 100644
index 0000000..ba48feb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c32029d5683ad5cfa1af3b534c53bc2f7f513f50
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c370cb2ce56d1006fea0af1a823042927c0cfa07 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c370cb2ce56d1006fea0af1a823042927c0cfa07
new file mode 100644
index 0000000..e1fe503
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c370cb2ce56d1006fea0af1a823042927c0cfa07
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c3ade78c7fea61ed2e2cd843f9c551b107ae050f b/test/core/end2end/fuzzers/api_fuzzer_corpus/c3ade78c7fea61ed2e2cd843f9c551b107ae050f
new file mode 100644
index 0000000..1a08ade
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c3ade78c7fea61ed2e2cd843f9c551b107ae050f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c40e43a76f0c493414386dd90ab892042a6914d2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c40e43a76f0c493414386dd90ab892042a6914d2
new file mode 100644
index 0000000..5f31d6c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c40e43a76f0c493414386dd90ab892042a6914d2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c4b438b82ac86439296c31dd7de86a753034c807 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c4b438b82ac86439296c31dd7de86a753034c807
new file mode 100644
index 0000000..b01f9a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c4b438b82ac86439296c31dd7de86a753034c807
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5154ce0384c3becaf12f83c51114bb3ccd0b673 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5154ce0384c3becaf12f83c51114bb3ccd0b673
new file mode 100644
index 0000000..ceaa6d2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5154ce0384c3becaf12f83c51114bb3ccd0b673
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5446cba5971d6f44ee93097a21c1b8936f4020a b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5446cba5971d6f44ee93097a21c1b8936f4020a
new file mode 100644
index 0000000..665d261
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5446cba5971d6f44ee93097a21c1b8936f4020a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c6733483e94f755f1cbf796f8aa3d10a2c371aa3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6733483e94f755f1cbf796f8aa3d10a2c371aa3
new file mode 100644
index 0000000..084991d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6733483e94f755f1cbf796f8aa3d10a2c371aa3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c8f0972dabb904bc6d35ed576fc9a49eb2ed5273 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8f0972dabb904bc6d35ed576fc9a49eb2ed5273
new file mode 100644
index 0000000..2eb2813
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8f0972dabb904bc6d35ed576fc9a49eb2ed5273
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c93f16b5b678d3019eb05bd0774598e7d34e9b3b b/test/core/end2end/fuzzers/api_fuzzer_corpus/c93f16b5b678d3019eb05bd0774598e7d34e9b3b
new file mode 100644
index 0000000..2f79043
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c93f16b5b678d3019eb05bd0774598e7d34e9b3b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c97c41c0c76a901f458bf9b4d785fb53fe8a2980 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c97c41c0c76a901f458bf9b4d785fb53fe8a2980
new file mode 100644
index 0000000..716844f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c97c41c0c76a901f458bf9b4d785fb53fe8a2980
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ca418a61964cb360014b574fe29aa20b193df04f b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca418a61964cb360014b574fe29aa20b193df04f
new file mode 100644
index 0000000..31eaf39
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca418a61964cb360014b574fe29aa20b193df04f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cb9a688f0dbc2015c77920f344e2d029c87384ff b/test/core/end2end/fuzzers/api_fuzzer_corpus/cb9a688f0dbc2015c77920f344e2d029c87384ff
new file mode 100644
index 0000000..e0f0ba5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cb9a688f0dbc2015c77920f344e2d029c87384ff
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd779b587b80719e2838853c2eac8d4595c0faa4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd779b587b80719e2838853c2eac8d4595c0faa4
new file mode 100644
index 0000000..4067a15
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd779b587b80719e2838853c2eac8d4595c0faa4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e b/test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e
new file mode 100644
index 0000000..1a58450
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d079f5c8a10611dc655cef33f73100f5f43787a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d079f5c8a10611dc655cef33f73100f5f43787a8
new file mode 100644
index 0000000..ac6ea53
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d079f5c8a10611dc655cef33f73100f5f43787a8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d107d21374f4dba27f173d4edd5c8009e3b0f8c4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d107d21374f4dba27f173d4edd5c8009e3b0f8c4
new file mode 100644
index 0000000..b888d62
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d107d21374f4dba27f173d4edd5c8009e3b0f8c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d110d5d3a672bf483f230825e735d372b0b2c1a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d110d5d3a672bf483f230825e735d372b0b2c1a5
new file mode 100644
index 0000000..1e3df71
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d110d5d3a672bf483f230825e735d372b0b2c1a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b2a1520207761100992c88b50f6b410c62184 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b2a1520207761100992c88b50f6b410c62184
new file mode 100644
index 0000000..9510bc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d18b2a1520207761100992c88b50f6b410c62184
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d22287b96b3dcb840fc65e4be60e409fb0f6bfe5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d22287b96b3dcb840fc65e4be60e409fb0f6bfe5
new file mode 100644
index 0000000..7e5f56c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d22287b96b3dcb840fc65e4be60e409fb0f6bfe5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d27e050b2758f6658d166b0d30e9db9595388ef9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d27e050b2758f6658d166b0d30e9db9595388ef9
new file mode 100644
index 0000000..7151cc3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d27e050b2758f6658d166b0d30e9db9595388ef9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d3089d3ef9be14080abc156e5f2128c3c1a2f23a b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3089d3ef9be14080abc156e5f2128c3c1a2f23a
new file mode 100644
index 0000000..f4e8b74
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3089d3ef9be14080abc156e5f2128c3c1a2f23a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d3090a5221ea984dc474c3fb448b71957f8197a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3090a5221ea984dc474c3fb448b71957f8197a4
new file mode 100644
index 0000000..bad0572
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d3090a5221ea984dc474c3fb448b71957f8197a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d56b3dae753b110e9e1a050486c6deb6ac399bd8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d56b3dae753b110e9e1a050486c6deb6ac399bd8
new file mode 100644
index 0000000..c290ccc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d56b3dae753b110e9e1a050486c6deb6ac399bd8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d576eb2948463f86f576d85e41d30a8cf3b972c2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d576eb2948463f86f576d85e41d30a8cf3b972c2
new file mode 100644
index 0000000..85d31ea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d576eb2948463f86f576d85e41d30a8cf3b972c2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d5824da8aeaf96a9e5f590a851e58e2534d178a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5824da8aeaf96a9e5f590a851e58e2534d178a5
new file mode 100644
index 0000000..8901ee6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5824da8aeaf96a9e5f590a851e58e2534d178a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d67c22b4174555c3e596c58dc7c28e84b1da8353 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d67c22b4174555c3e596c58dc7c28e84b1da8353
new file mode 100644
index 0000000..cfe3992
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d67c22b4174555c3e596c58dc7c28e84b1da8353
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d68001237e6366c844a6509fa03e677e6adfb75f b/test/core/end2end/fuzzers/api_fuzzer_corpus/d68001237e6366c844a6509fa03e677e6adfb75f
new file mode 100644
index 0000000..796a3bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d68001237e6366c844a6509fa03e677e6adfb75f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d681712608025610b8ecc8a76a822516fb659953 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d681712608025610b8ecc8a76a822516fb659953
new file mode 100644
index 0000000..390be08
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d681712608025610b8ecc8a76a822516fb659953
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d87b7bcd1b05a2f8cc04a2aadb999bcf65b84911 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d87b7bcd1b05a2f8cc04a2aadb999bcf65b84911
new file mode 100644
index 0000000..8373407
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d87b7bcd1b05a2f8cc04a2aadb999bcf65b84911
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d8d117e45b7bc0c48f606d9ef844f00a363a8a38 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8d117e45b7bc0c48f606d9ef844f00a363a8a38
new file mode 100644
index 0000000..dad8cbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8d117e45b7bc0c48f606d9ef844f00a363a8a38
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d99bfa6bb10d30f64b533ea7620fc08b762a7bf3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d99bfa6bb10d30f64b533ea7620fc08b762a7bf3
new file mode 100644
index 0000000..e4df6b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d99bfa6bb10d30f64b533ea7620fc08b762a7bf3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d9d80422059678f0a011b8e8fdedd3d20c025b91 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d9d80422059678f0a011b8e8fdedd3d20c025b91
new file mode 100644
index 0000000..bf45710
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d9d80422059678f0a011b8e8fdedd3d20c025b91
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/da2ace62505959bae7b4f158220f7ce97d20423d b/test/core/end2end/fuzzers/api_fuzzer_corpus/da2ace62505959bae7b4f158220f7ce97d20423d
new file mode 100644
index 0000000..4275d96
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/da2ace62505959bae7b4f158220f7ce97d20423d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dac17b9025074828797ef0dd1e3895baf875627f b/test/core/end2end/fuzzers/api_fuzzer_corpus/dac17b9025074828797ef0dd1e3895baf875627f
new file mode 100644
index 0000000..98d1f0f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dac17b9025074828797ef0dd1e3895baf875627f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/db0dbec7a0811cac7b250cf9b248d47936edc0d0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/db0dbec7a0811cac7b250cf9b248d47936edc0d0
new file mode 100644
index 0000000..71bc27a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/db0dbec7a0811cac7b250cf9b248d47936edc0d0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dc38c75bcb7df7e61428d8f12ff01a1ec1b68a99 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dc38c75bcb7df7e61428d8f12ff01a1ec1b68a99
new file mode 100644
index 0000000..8dbf962
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dc38c75bcb7df7e61428d8f12ff01a1ec1b68a99
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc8e14bbb75292968233ce89acd404303a53cc3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc8e14bbb75292968233ce89acd404303a53cc3
new file mode 100644
index 0000000..e6db861
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc8e14bbb75292968233ce89acd404303a53cc3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dcd0182c3027a0d6cc7a9a8c26f647d45bf3d3df b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcd0182c3027a0d6cc7a9a8c26f647d45bf3d3df
new file mode 100644
index 0000000..22cb1d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcd0182c3027a0d6cc7a9a8c26f647d45bf3d3df
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/deb08a636c04030bc28459820c7ddbace429b40a b/test/core/end2end/fuzzers/api_fuzzer_corpus/deb08a636c04030bc28459820c7ddbace429b40a
new file mode 100644
index 0000000..73cfa51
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/deb08a636c04030bc28459820c7ddbace429b40a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df106c9859b09869094c77aeba44e6e9ce909246 b/test/core/end2end/fuzzers/api_fuzzer_corpus/df106c9859b09869094c77aeba44e6e9ce909246
new file mode 100644
index 0000000..193f219
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df106c9859b09869094c77aeba44e6e9ce909246
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df380dfd997318c00cfc75313e6a7ecb041d38af b/test/core/end2end/fuzzers/api_fuzzer_corpus/df380dfd997318c00cfc75313e6a7ecb041d38af
new file mode 100644
index 0000000..8d27db7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df380dfd997318c00cfc75313e6a7ecb041d38af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe4f327699ddea25103dd17b68e9a0fb726f4a7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe4f327699ddea25103dd17b68e9a0fb726f4a7
new file mode 100644
index 0000000..1a32983
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dfe4f327699ddea25103dd17b68e9a0fb726f4a7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e007d8c9aa6c37e8b62fab4cb95b2807fc49105f b/test/core/end2end/fuzzers/api_fuzzer_corpus/e007d8c9aa6c37e8b62fab4cb95b2807fc49105f
new file mode 100644
index 0000000..ba60670
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e007d8c9aa6c37e8b62fab4cb95b2807fc49105f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e0507daae4458401edc11e5c76b246d6d5a44e3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0507daae4458401edc11e5c76b246d6d5a44e3d
new file mode 100644
index 0000000..538f1c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0507daae4458401edc11e5c76b246d6d5a44e3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e08b85aa24c9d0a49f8946c8400b86b5ea9211c8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e08b85aa24c9d0a49f8946c8400b86b5ea9211c8
new file mode 100644
index 0000000..8cb2d39
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e08b85aa24c9d0a49f8946c8400b86b5ea9211c8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e0b7eb44f182f08d2eeaeecc76ef7b3efeff1fc4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0b7eb44f182f08d2eeaeecc76ef7b3efeff1fc4
new file mode 100644
index 0000000..7c8ba6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e0b7eb44f182f08d2eeaeecc76ef7b3efeff1fc4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e13361499a2326ef8dbc3746ceb61c61b2e1ad57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e13361499a2326ef8dbc3746ceb61c61b2e1ad57
new file mode 100644
index 0000000..0b6c3a5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e13361499a2326ef8dbc3746ceb61c61b2e1ad57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e15a0a0fb7b4f1c05088bc119c492ac20eb5dbcf b/test/core/end2end/fuzzers/api_fuzzer_corpus/e15a0a0fb7b4f1c05088bc119c492ac20eb5dbcf
new file mode 100644
index 0000000..7b286e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e15a0a0fb7b4f1c05088bc119c492ac20eb5dbcf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e192ba28f8a3bc9079b810c46ecc526f84609863 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e192ba28f8a3bc9079b810c46ecc526f84609863
new file mode 100644
index 0000000..b09975e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e192ba28f8a3bc9079b810c46ecc526f84609863
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e33eb4b19232b2e32bc8f18e43459c4ed15bfc4f b/test/core/end2end/fuzzers/api_fuzzer_corpus/e33eb4b19232b2e32bc8f18e43459c4ed15bfc4f
new file mode 100644
index 0000000..89915b2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e33eb4b19232b2e32bc8f18e43459c4ed15bfc4f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e3b45752c8160c48885420e20c24bb7124128f16 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3b45752c8160c48885420e20c24bb7124128f16
new file mode 100644
index 0000000..9fa2755
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3b45752c8160c48885420e20c24bb7124128f16
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e3c1dbfb1ef140f6bdcf7d683e2b2071aacba9ba b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3c1dbfb1ef140f6bdcf7d683e2b2071aacba9ba
new file mode 100644
index 0000000..7276b85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3c1dbfb1ef140f6bdcf7d683e2b2071aacba9ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e3eda76a93e94d081a9dfd675975fe2fc1d670dc b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3eda76a93e94d081a9dfd675975fe2fc1d670dc
new file mode 100644
index 0000000..c02b7ef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e3eda76a93e94d081a9dfd675975fe2fc1d670dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e53a201505fe8412278d7444b1a915b353bacb3e b/test/core/end2end/fuzzers/api_fuzzer_corpus/e53a201505fe8412278d7444b1a915b353bacb3e
new file mode 100644
index 0000000..21c4cee
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e53a201505fe8412278d7444b1a915b353bacb3e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e7484552736c89fe721019daaad8739a68f1a926 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e7484552736c89fe721019daaad8739a68f1a926
new file mode 100644
index 0000000..10b40e6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e7484552736c89fe721019daaad8739a68f1a926
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e80302182fbd464b72d2b9be495901c0c3e93344 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e80302182fbd464b72d2b9be495901c0c3e93344
new file mode 100644
index 0000000..b5081f4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e80302182fbd464b72d2b9be495901c0c3e93344
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e805c33631e579c782550439f123b78e1ad8e180 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e805c33631e579c782550439f123b78e1ad8e180
new file mode 100644
index 0000000..1615258
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e805c33631e579c782550439f123b78e1ad8e180
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eab01c8a32e76c8f354055807399a808848234e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eab01c8a32e76c8f354055807399a808848234e6
new file mode 100644
index 0000000..c21869e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eab01c8a32e76c8f354055807399a808848234e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ebc30c5cbe17138976223f2283fe42d9e4c6f39a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebc30c5cbe17138976223f2283fe42d9e4c6f39a
new file mode 100644
index 0000000..060185d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebc30c5cbe17138976223f2283fe42d9e4c6f39a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ebe414975652c12fbbfd99efd2da1cd4c72c340c b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebe414975652c12fbbfd99efd2da1cd4c72c340c
new file mode 100644
index 0000000..0ce6c54
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ebe414975652c12fbbfd99efd2da1cd4c72c340c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec230c6a27149df85cad53f33478ffc11bd92d4e b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec230c6a27149df85cad53f33478ffc11bd92d4e
new file mode 100644
index 0000000..c0669bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec230c6a27149df85cad53f33478ffc11bd92d4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec97d4ee730261bdc3b14349a3346fd45929bd17 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec97d4ee730261bdc3b14349a3346fd45929bd17
new file mode 100644
index 0000000..1a44000
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec97d4ee730261bdc3b14349a3346fd45929bd17
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ecf0a3cd157191263734f4f2de9689d5a02e439b b/test/core/end2end/fuzzers/api_fuzzer_corpus/ecf0a3cd157191263734f4f2de9689d5a02e439b
new file mode 100644
index 0000000..0fa5213
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ecf0a3cd157191263734f4f2de9689d5a02e439b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ed361ec32383606748bedeb8eee6510041b0f366 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed361ec32383606748bedeb8eee6510041b0f366
new file mode 100644
index 0000000..79a8ba2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed361ec32383606748bedeb8eee6510041b0f366
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/edcf7ea2ec8443a92883e68e5e18353fad8f6d21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/edcf7ea2ec8443a92883e68e5e18353fad8f6d21
new file mode 100644
index 0000000..3e66166
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/edcf7ea2ec8443a92883e68e5e18353fad8f6d21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef32866f14ccd80c1231fa742b53fba46ae15d6f b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef32866f14ccd80c1231fa742b53fba46ae15d6f
new file mode 100644
index 0000000..d7c207d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef32866f14ccd80c1231fa742b53fba46ae15d6f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef63ab3c4dbf27ed1f15c2b310bf41ff3a2a7e3c b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef63ab3c4dbf27ed1f15c2b310bf41ff3a2a7e3c
new file mode 100644
index 0000000..d8edea8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef63ab3c4dbf27ed1f15c2b310bf41ff3a2a7e3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef967ba35676b971983b1e95e62c383a978a37f7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef967ba35676b971983b1e95e62c383a978a37f7
new file mode 100644
index 0000000..4d372b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef967ba35676b971983b1e95e62c383a978a37f7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eff00cadc3130c257b3fe360ea5d32fb034aadff b/test/core/end2end/fuzzers/api_fuzzer_corpus/eff00cadc3130c257b3fe360ea5d32fb034aadff
new file mode 100644
index 0000000..42c38de
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eff00cadc3130c257b3fe360ea5d32fb034aadff
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f0649728d5f9e1a91735eaa429605ce0da6c00c0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0649728d5f9e1a91735eaa429605ce0da6c00c0
new file mode 100644
index 0000000..877aed3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0649728d5f9e1a91735eaa429605ce0da6c00c0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f0d881bdd69c3945694068719a7a6b6b094dee3c b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0d881bdd69c3945694068719a7a6b6b094dee3c
new file mode 100644
index 0000000..9da6998
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f0d881bdd69c3945694068719a7a6b6b094dee3c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f18f2d094ef0f0c971173153279bc44bfa3c1187 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f18f2d094ef0f0c971173153279bc44bfa3c1187
new file mode 100644
index 0000000..606dcad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f18f2d094ef0f0c971173153279bc44bfa3c1187
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a7981f4f19f6318e0f16cafe9541d1564f9e15 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a7981f4f19f6318e0f16cafe9541d1564f9e15
new file mode 100644
index 0000000..18aea88
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1a7981f4f19f6318e0f16cafe9541d1564f9e15
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f27ae36fe8211e46f49656597658daab1429b163 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f27ae36fe8211e46f49656597658daab1429b163
new file mode 100644
index 0000000..3f94e68
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f27ae36fe8211e46f49656597658daab1429b163
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f2f014c6ef70e40f9334096f34584ea4f1f882d7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2f014c6ef70e40f9334096f34584ea4f1f882d7
new file mode 100644
index 0000000..eb8e03b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2f014c6ef70e40f9334096f34584ea4f1f882d7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f463b733bfacabdd064c6b5a0551d72398f833af b/test/core/end2end/fuzzers/api_fuzzer_corpus/f463b733bfacabdd064c6b5a0551d72398f833af
new file mode 100644
index 0000000..03ad61f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f463b733bfacabdd064c6b5a0551d72398f833af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f5867f7dbacd22878e2955f4be8fca147442aa9d b/test/core/end2end/fuzzers/api_fuzzer_corpus/f5867f7dbacd22878e2955f4be8fca147442aa9d
new file mode 100644
index 0000000..0ea1096
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f5867f7dbacd22878e2955f4be8fca147442aa9d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f5a7503830d1e74c6a7230c10c5007a5f8ad5a0f b/test/core/end2end/fuzzers/api_fuzzer_corpus/f5a7503830d1e74c6a7230c10c5007a5f8ad5a0f
new file mode 100644
index 0000000..9a522be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f5a7503830d1e74c6a7230c10c5007a5f8ad5a0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f62ae81e655f294699b73830d3abaa787196cb23 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f62ae81e655f294699b73830d3abaa787196cb23
new file mode 100644
index 0000000..fdba78b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f62ae81e655f294699b73830d3abaa787196cb23
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7316eaa3f54119ac5b7fb24e8b92debdf57c3f1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7316eaa3f54119ac5b7fb24e8b92debdf57c3f1
new file mode 100644
index 0000000..35d4f9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7316eaa3f54119ac5b7fb24e8b92debdf57c3f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7909263cd7edc56186185c0b3421ebb68ad8d2b b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7909263cd7edc56186185c0b3421ebb68ad8d2b
new file mode 100644
index 0000000..9ba6a4b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7909263cd7edc56186185c0b3421ebb68ad8d2b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f912a072f4abf312ebbe7f1a2bf5ebd8c51e35e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f912a072f4abf312ebbe7f1a2bf5ebd8c51e35e2
new file mode 100644
index 0000000..9e85aa9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f912a072f4abf312ebbe7f1a2bf5ebd8c51e35e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fa44038e372af4ab374d3e94ec61662051e0dd74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa44038e372af4ab374d3e94ec61662051e0dd74
new file mode 100644
index 0000000..ca4f7a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fa44038e372af4ab374d3e94ec61662051e0dd74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/faa0471930dc99deb5b1ffdc9bab7c1267b4ddbb b/test/core/end2end/fuzzers/api_fuzzer_corpus/faa0471930dc99deb5b1ffdc9bab7c1267b4ddbb
new file mode 100644
index 0000000..52cb2f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/faa0471930dc99deb5b1ffdc9bab7c1267b4ddbb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fac54fba5614e5930104bc7391773b490c0523b2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fac54fba5614e5930104bc7391773b490c0523b2
new file mode 100644
index 0000000..e13f8bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fac54fba5614e5930104bc7391773b490c0523b2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bef1e4142a7bcfa30e93f834fb6315438d1ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bef1e4142a7bcfa30e93f834fb6315438d1ad
new file mode 100644
index 0000000..9953e92
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bef1e4142a7bcfa30e93f834fb6315438d1ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9ad6fd8276dd9b38b27ee8907f0db5a3a2cedf b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9ad6fd8276dd9b38b27ee8907f0db5a3a2cedf
new file mode 100644
index 0000000..de59951
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb9ad6fd8276dd9b38b27ee8907f0db5a3a2cedf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fbeb44db0fc0f6b70c226053448c7170f62543b1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fbeb44db0fc0f6b70c226053448c7170f62543b1
new file mode 100644
index 0000000..62826f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fbeb44db0fc0f6b70c226053448c7170f62543b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc39c0c12cde4ef57c217955886ed9508214ca98 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc39c0c12cde4ef57c217955886ed9508214ca98
new file mode 100644
index 0000000..378d150
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc39c0c12cde4ef57c217955886ed9508214ca98
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda
new file mode 100644
index 0000000..53ad5a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fe565289309a897d640309b9bf214d3036c2216b b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe565289309a897d640309b9bf214d3036c2216b
new file mode 100644
index 0000000..f9614e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe565289309a897d640309b9bf214d3036c2216b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fe7ac5c3403c7f1673ead3176af4efe7c60b2c02 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe7ac5c3403c7f1673ead3176af4efe7c60b2c02
new file mode 100644
index 0000000..38d0e2e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe7ac5c3403c7f1673ead3176af4efe7c60b2c02
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fe9d7f510475f17a7592213c9b2e614ce7d38f22 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe9d7f510475f17a7592213c9b2e614ce7d38f22
new file mode 100644
index 0000000..6929f70
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe9d7f510475f17a7592213c9b2e614ce7d38f22
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ff2fd7bfc554729dc2a40554597e3a95ab8baefe b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff2fd7bfc554729dc2a40554597e3a95ab8baefe
new file mode 100644
index 0000000..617703e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff2fd7bfc554729dc2a40554597e3a95ab8baefe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ff8ffcfafaf420d6fee1cfa087204975ab8e14d6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff8ffcfafaf420d6fee1cfa087204975ab8e14d6
new file mode 100644
index 0000000..3308bf2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff8ffcfafaf420d6fee1cfa087204975ab8e14d6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ffc74f2184f64032a1f67b5f843a683ea1372b74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ffc74f2184f64032a1f67b5f843a683ea1372b74
new file mode 100644
index 0000000..ea81a9f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ffc74f2184f64032a1f67b5f843a683ea1372b74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/full_request.bin b/test/core/end2end/fuzzers/api_fuzzer_corpus/full_request.bin
new file mode 100644
index 0000000..144e618
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/full_request.bin
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/04bef86965e816c0cd330896ecd981dd3b14275c b/test/core/end2end/fuzzers/client_fuzzer_corpus/04bef86965e816c0cd330896ecd981dd3b14275c
new file mode 100644
index 0000000..c90168f
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/04bef86965e816c0cd330896ecd981dd3b14275c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/0c6f2e0a2232788cb20c4f52ffa18d7ab8f0b938 b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c6f2e0a2232788cb20c4f52ffa18d7ab8f0b938
new file mode 100644
index 0000000..1db6475
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/0c6f2e0a2232788cb20c4f52ffa18d7ab8f0b938
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/1526ac4266e152b029b7c283255fe4fb6507f726 b/test/core/end2end/fuzzers/client_fuzzer_corpus/1526ac4266e152b029b7c283255fe4fb6507f726
new file mode 100644
index 0000000..c255893
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/1526ac4266e152b029b7c283255fe4fb6507f726
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/15c8bfec99ff18b11211d464c824fc139cc791fd b/test/core/end2end/fuzzers/client_fuzzer_corpus/15c8bfec99ff18b11211d464c824fc139cc791fd
new file mode 100644
index 0000000..394b1cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/15c8bfec99ff18b11211d464c824fc139cc791fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/169f579e66b4b8ff423891a40380e648e8d45247 b/test/core/end2end/fuzzers/client_fuzzer_corpus/169f579e66b4b8ff423891a40380e648e8d45247
new file mode 100644
index 0000000..7b1498d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/169f579e66b4b8ff423891a40380e648e8d45247
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/23e8c1377addaf67019ea36a084e0b68ca7a33db b/test/core/end2end/fuzzers/client_fuzzer_corpus/23e8c1377addaf67019ea36a084e0b68ca7a33db
new file mode 100644
index 0000000..5dd8b4d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/23e8c1377addaf67019ea36a084e0b68ca7a33db
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/25d2969baf8bd256e15b2ab72707682b2d18b40a b/test/core/end2end/fuzzers/client_fuzzer_corpus/25d2969baf8bd256e15b2ab72707682b2d18b40a
new file mode 100644
index 0000000..5a8b49d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/25d2969baf8bd256e15b2ab72707682b2d18b40a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/2862adc802092f1a422416a1666a5142f71d5d7f b/test/core/end2end/fuzzers/client_fuzzer_corpus/2862adc802092f1a422416a1666a5142f71d5d7f
new file mode 100644
index 0000000..04f59c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/2862adc802092f1a422416a1666a5142f71d5d7f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/28680d04887f96a1167dd913573ec8daa2a39625 b/test/core/end2end/fuzzers/client_fuzzer_corpus/28680d04887f96a1167dd913573ec8daa2a39625
new file mode 100644
index 0000000..8cf466e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/28680d04887f96a1167dd913573ec8daa2a39625
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/28f54e558b181e294e101447c7a79d976fe36fcb b/test/core/end2end/fuzzers/client_fuzzer_corpus/28f54e558b181e294e101447c7a79d976fe36fcb
new file mode 100644
index 0000000..88efbe2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/28f54e558b181e294e101447c7a79d976fe36fcb
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3c01b1f89d50fa37fcb3457cd3dd6502fe84e25b b/test/core/end2end/fuzzers/client_fuzzer_corpus/3c01b1f89d50fa37fcb3457cd3dd6502fe84e25b
new file mode 100644
index 0000000..11152e5
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3c01b1f89d50fa37fcb3457cd3dd6502fe84e25b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4097094277bc09981f428280fc0cc0f590f20ded b/test/core/end2end/fuzzers/client_fuzzer_corpus/4097094277bc09981f428280fc0cc0f590f20ded
new file mode 100644
index 0000000..4bbae55
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4097094277bc09981f428280fc0cc0f590f20ded
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/44b6be630161765a3de5872629602ca14789c3bd b/test/core/end2end/fuzzers/client_fuzzer_corpus/44b6be630161765a3de5872629602ca14789c3bd
new file mode 100644
index 0000000..45628da
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/44b6be630161765a3de5872629602ca14789c3bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/49c5568cb0de363bc9f9298f1eacaace6c8a268a b/test/core/end2end/fuzzers/client_fuzzer_corpus/49c5568cb0de363bc9f9298f1eacaace6c8a268a
new file mode 100644
index 0000000..ee05f83
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/49c5568cb0de363bc9f9298f1eacaace6c8a268a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/54555ceac4403855f4cf20367f7be05714c46c51 b/test/core/end2end/fuzzers/client_fuzzer_corpus/54555ceac4403855f4cf20367f7be05714c46c51
new file mode 100644
index 0000000..f075bd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/54555ceac4403855f4cf20367f7be05714c46c51
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5821752bf8923fdaebc8484662624d8acd382716 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5821752bf8923fdaebc8484662624d8acd382716
new file mode 100644
index 0000000..599622a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5821752bf8923fdaebc8484662624d8acd382716
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/59d28886db21f371ac9d999b68b116bcf425d971 b/test/core/end2end/fuzzers/client_fuzzer_corpus/59d28886db21f371ac9d999b68b116bcf425d971
new file mode 100644
index 0000000..8b16036
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/59d28886db21f371ac9d999b68b116bcf425d971
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/690158fb146f7f3b3ea820979307a8d8e6f38314 b/test/core/end2end/fuzzers/client_fuzzer_corpus/690158fb146f7f3b3ea820979307a8d8e6f38314
new file mode 100644
index 0000000..e914451
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/690158fb146f7f3b3ea820979307a8d8e6f38314
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6ca3910d5f4f7967311853724b072750716dcb48 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6ca3910d5f4f7967311853724b072750716dcb48
new file mode 100644
index 0000000..b9d8763
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6ca3910d5f4f7967311853724b072750716dcb48
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/6f30de3096eb71f697885fdd9cbddd9ee6ce46c4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/6f30de3096eb71f697885fdd9cbddd9ee6ce46c4
new file mode 100644
index 0000000..fff1abb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/6f30de3096eb71f697885fdd9cbddd9ee6ce46c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7f1530d4b702e68d043f89d9e63d314319dcd803 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7f1530d4b702e68d043f89d9e63d314319dcd803
new file mode 100644
index 0000000..cee4bfa
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7f1530d4b702e68d043f89d9e63d314319dcd803
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/85a7e47ef707d3b31cad924ed6c697c3678ab569 b/test/core/end2end/fuzzers/client_fuzzer_corpus/85a7e47ef707d3b31cad924ed6c697c3678ab569
new file mode 100644
index 0000000..4606930
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/85a7e47ef707d3b31cad924ed6c697c3678ab569
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/911e2ea20b6c10431e48f70d9933987815926a9d b/test/core/end2end/fuzzers/client_fuzzer_corpus/911e2ea20b6c10431e48f70d9933987815926a9d
new file mode 100644
index 0000000..d99f977
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/911e2ea20b6c10431e48f70d9933987815926a9d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/93ac93b7deabdfb4f86eb37a1e9f6669957d14a6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/93ac93b7deabdfb4f86eb37a1e9f6669957d14a6
new file mode 100644
index 0000000..1eeb93d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/93ac93b7deabdfb4f86eb37a1e9f6669957d14a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9eaf2ad607a943141c29f334b2c66c2e59e99980 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9eaf2ad607a943141c29f334b2c66c2e59e99980
new file mode 100644
index 0000000..3006681
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9eaf2ad607a943141c29f334b2c66c2e59e99980
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a210d629c305b89a34b7ff3c41ae4566cd22186b b/test/core/end2end/fuzzers/client_fuzzer_corpus/a210d629c305b89a34b7ff3c41ae4566cd22186b
new file mode 100644
index 0000000..07aab36
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a210d629c305b89a34b7ff3c41ae4566cd22186b
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a29a547671badd3154789e1a02bdb87332fcd6a4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a29a547671badd3154789e1a02bdb87332fcd6a4
new file mode 100644
index 0000000..a2cd476
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a29a547671badd3154789e1a02bdb87332fcd6a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a5592f15d5424ab7e16a18e77027ab91c846d90a b/test/core/end2end/fuzzers/client_fuzzer_corpus/a5592f15d5424ab7e16a18e77027ab91c846d90a
new file mode 100644
index 0000000..4b62307
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a5592f15d5424ab7e16a18e77027ab91c846d90a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/a5cf80b996b2ba8c9580f8ecd22720c48de41044 b/test/core/end2end/fuzzers/client_fuzzer_corpus/a5cf80b996b2ba8c9580f8ecd22720c48de41044
new file mode 100644
index 0000000..64f9923
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/a5cf80b996b2ba8c9580f8ecd22720c48de41044
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b24c25c6d4b57a5f3d64a0adb205bf4f150c9138 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b24c25c6d4b57a5f3d64a0adb205bf4f150c9138
new file mode 100644
index 0000000..43de954
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b24c25c6d4b57a5f3d64a0adb205bf4f150c9138
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/beabbe93f1e9b2e56f729af30559ec03a00f53fa b/test/core/end2end/fuzzers/client_fuzzer_corpus/beabbe93f1e9b2e56f729af30559ec03a00f53fa
new file mode 100644
index 0000000..d248d89
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/beabbe93f1e9b2e56f729af30559ec03a00f53fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/cbe59c62c6d36c7307c438159327e320cd2fcf57 b/test/core/end2end/fuzzers/client_fuzzer_corpus/cbe59c62c6d36c7307c438159327e320cd2fcf57
new file mode 100644
index 0000000..872bc35
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/cbe59c62c6d36c7307c438159327e320cd2fcf57
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ce1c326f3b0147841550ce3b5126390764bae8e8 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ce1c326f3b0147841550ce3b5126390764bae8e8
new file mode 100644
index 0000000..5de9280
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ce1c326f3b0147841550ce3b5126390764bae8e8
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d21ca2b01baa21a666257d1a1e0275587eeb565d b/test/core/end2end/fuzzers/client_fuzzer_corpus/d21ca2b01baa21a666257d1a1e0275587eeb565d
new file mode 100644
index 0000000..40e3961
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d21ca2b01baa21a666257d1a1e0275587eeb565d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d2f71a800612876010558ce804c9a72ad0a1b9fc b/test/core/end2end/fuzzers/client_fuzzer_corpus/d2f71a800612876010558ce804c9a72ad0a1b9fc
new file mode 100644
index 0000000..b501115
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d2f71a800612876010558ce804c9a72ad0a1b9fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d637cc9387087de633b9db535d19f64795c43be1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d637cc9387087de633b9db535d19f64795c43be1
new file mode 100644
index 0000000..a43faf9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d637cc9387087de633b9db535d19f64795c43be1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/dd5ac34f5b220970447b2733848de78570c47883 b/test/core/end2end/fuzzers/client_fuzzer_corpus/dd5ac34f5b220970447b2733848de78570c47883
new file mode 100644
index 0000000..848969d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/dd5ac34f5b220970447b2733848de78570c47883
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f2a6bb4e0137541e2b140b976764377d07d822d6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f2a6bb4e0137541e2b140b976764377d07d822d6
new file mode 100644
index 0000000..8af994e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f2a6bb4e0137541e2b140b976764377d07d822d6
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 4027371..0a7d6d9 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -69,7 +69,7 @@
   grpc_server_start(server);
   grpc_transport *transport =
       grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 0);
-  grpc_server_setup_transport(&exec_ctx, server, transport, NULL);
+  grpc_server_setup_transport(&exec_ctx, server, transport, NULL, NULL);
   grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0);
 
   grpc_call *call1 = NULL;
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index b555bea..5c6791f 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -42,7 +42,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/string.h"
 #include "test/core/end2end/cq_verifier.h"
 
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index 779895b..f5a8d4d 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -105,7 +105,7 @@
   gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
   grpc_byte_buffer *request_payload =
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
-  gpr_timespec deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10);
+  gpr_timespec deadline = five_seconds_time();
   grpc_end2end_test_fixture f =
       begin_test(config, "test_invoke_request_with_flags", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 266d239..222ae77 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -113,6 +113,7 @@
 }
 
 static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
+                       grpc_pollset *pollset,
                        grpc_tcp_server_acceptor *acceptor) {
   grpc_endpoint_shutdown(exec_ctx, tcp);
   grpc_endpoint_destroy(exec_ctx, tcp);
diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c
index 1e7e4fa..3152fb7 100644
--- a/test/core/iomgr/udp_server_test.c
+++ b/test/core/iomgr/udp_server_test.c
@@ -111,7 +111,7 @@
   grpc_udp_server_destroy(&exec_ctx, s, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 
-  /* The server had a single FD, which should be orphaned. */
+  /* The server had a single FD, which should have been orphaned. */
   GPR_ASSERT(g_number_of_orphan_calls == 1);
 }
 
@@ -132,7 +132,7 @@
   grpc_udp_server_destroy(&exec_ctx, s, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 
-  /* The server had a single FD which should be orphaned. */
+  /* The server had a single FD, which should have been orphaned. */
   GPR_ASSERT(g_number_of_orphan_calls == 1);
 }
 
@@ -195,7 +195,8 @@
   grpc_udp_server_destroy(&exec_ctx, s, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 
-  GPR_ASSERT(g_number_of_orphan_calls == 5);
+  /* The server had a single FD, which should have been orphaned. */
+  GPR_ASSERT(g_number_of_orphan_calls == 1);
 }
 
 static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c
index d1ead16..e2f44eb 100644
--- a/test/core/security/auth_context_test.c
+++ b/test/core/security/auth_context_test.c
@@ -33,7 +33,7 @@
 
 #include <string.h>
 
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/support/string.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/security/b64_test.c b/test/core/security/b64_test.c
index cea8703..b26bd02 100644
--- a/test/core/security/b64_test.c
+++ b/test/core/security/b64_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/lib/security/b64.h"
+#include "src/core/lib/security/util/b64.h"
 
 #include <string.h>
 
diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c
index 6d4707f..3c36b76 100644
--- a/test/core/security/create_jwt.c
+++ b/test/core/security/create_jwt.c
@@ -34,8 +34,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
 #include "src/core/lib/support/load_file.h"
 
 #include <grpc/support/alloc.h>
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 7867293..31e0637 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -33,7 +33,7 @@
 
 #include <grpc/support/port_platform.h>
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 
 #include <openssl/rsa.h>
 #include <stdlib.h>
@@ -45,7 +45,10 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/security/credentials/composite/composite_credentials.h"
+#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
+#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
+#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index bd314e9..2a102fb 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -42,7 +42,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/load_file.h"
 #include "test/core/security/oauth2_utils.h"
 
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index 3aee52e..405fe56 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/security/credentials/jwt/json_token.h"
 
 #include <openssl/evp.h>
 #include <string.h>
@@ -42,7 +42,8 @@
 #include <grpc/support/slice.h>
 
 #include "src/core/lib/json/json.h"
-#include "src/core/lib/security/b64.h"
+#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
+#include "src/core/lib/security/util/b64.h"
 #include "test/core/util/test_config.h"
 
 /* This JSON key was generated with the GCE console and revoked immediately.
diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c
index 077f44d..7f4f4ff 100644
--- a/test/core/security/jwt_verifier_test.c
+++ b/test/core/security/jwt_verifier_test.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/lib/security/jwt_verifier.h"
+#include "src/core/lib/security/credentials/jwt/jwt_verifier.h"
 
 #include <string.h>
 
@@ -43,8 +43,8 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/security/b64.h"
-#include "src/core/lib/security/json_token.h"
+#include "src/core/lib/security/credentials/jwt/json_token.h"
+#include "src/core/lib/security/util/b64.h"
 #include "test/core/util/test_config.h"
 
 /* This JSON key was generated with the GCE console and revoked immediately.
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index 252355f..1d11370 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -42,7 +42,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 
 typedef struct {
   gpr_mu *mu;
diff --git a/test/core/security/oauth2_utils.h b/test/core/security/oauth2_utils.h
index eff9827..0f4e885 100644
--- a/test/core/security/oauth2_utils.h
+++ b/test/core/security/oauth2_utils.h
@@ -34,7 +34,7 @@
 #ifndef GRPC_TEST_CORE_SECURITY_OAUTH2_UTILS_H
 #define GRPC_TEST_CORE_SECURITY_OAUTH2_UTILS_H
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 79e2549..ef0e012 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -42,7 +42,8 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/composite/composite_credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/string.h"
 
 typedef struct {
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index aeaf382..6aba21a 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -41,7 +41,7 @@
 #include <grpc/support/log.h>
 #include "src/core/lib/iomgr/endpoint_pair.h"
 #include "src/core/lib/iomgr/iomgr.h"
-#include "src/core/lib/security/secure_endpoint.h"
+#include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/tsi/fake_transport_security.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
index 1a4e64b..6106bec 100644
--- a/test/core/security/security_connector_test.c
+++ b/test/core/security/security_connector_test.c
@@ -40,8 +40,8 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/lib/security/security_connector.h"
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/transport/security_connector.h"
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
index 2274fe1..ecb873b 100644
--- a/test/core/security/verify_jwt.c
+++ b/test/core/security/verify_jwt.c
@@ -42,7 +42,7 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
-#include "src/core/lib/security/jwt_verifier.h"
+#include "src/core/lib/security/credentials/jwt/jwt_verifier.h"
 
 typedef struct {
   grpc_pollset *pollset;
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index d62d5a9..49a1fc4 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -63,6 +63,12 @@
   shutdown_and_destroy(grpc_completion_queue_create(NULL));
 }
 
+static void test_pollset_conversion(void) {
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  GPR_ASSERT(grpc_cq_from_pollset(grpc_cq_pollset(cq)) == cq);
+  shutdown_and_destroy(cq);
+}
+
 static void test_wait_empty(void) {
   grpc_completion_queue *cc;
   grpc_event event;
@@ -408,6 +414,7 @@
   grpc_test_init(argc, argv);
   grpc_init();
   test_no_op();
+  test_pollset_conversion();
   test_wait_empty();
   test_shutdown_then_next_polling();
   test_shutdown_then_next_with_timeout();
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index 28ddf58..de9ba8d 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -96,6 +96,7 @@
 }
 
 static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
+                       grpc_pollset *accepting_pollset,
                        grpc_tcp_server_acceptor *acceptor) {
   struct server_thread_args *args = (struct server_thread_args *)vargs;
   (void)acceptor;
diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c
index 80419ef..b952503 100644
--- a/test/core/surface/secure_channel_create_test.c
+++ b/test/core/surface/secure_channel_create_test.c
@@ -37,8 +37,8 @@
 #include <grpc/grpc_security.h>
 #include <grpc/support/log.h>
 #include "src/core/ext/client_config/resolver_registry.h"
-#include "src/core/lib/security/credentials.h"
-#include "src/core/lib/security/security_connector.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
+#include "src/core/lib/security/transport/security_connector.h"
 #include "src/core/lib/surface/channel.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c
index d22c164..f42ca9f 100644
--- a/test/core/surface/server_chttp2_test.c
+++ b/test/core/surface/server_chttp2_test.c
@@ -37,7 +37,8 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
 #include "src/core/lib/tsi/fake_transport_security.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c
index 3d2e253..1e94c5a 100644
--- a/test/core/surface/server_test.c
+++ b/test/core/surface/server_test.c
@@ -67,12 +67,14 @@
 
 void test_request_call_on_no_server_cq(void) {
   grpc_completion_queue *cc = grpc_completion_queue_create(NULL);
+  grpc_server *server = grpc_server_create(NULL, NULL);
   GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE ==
-             grpc_server_request_call(NULL, NULL, NULL, NULL, cc, cc, NULL));
+             grpc_server_request_call(server, NULL, NULL, NULL, cc, cc, NULL));
   GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE ==
-             grpc_server_request_registered_call(NULL, NULL, NULL, NULL, NULL,
+             grpc_server_request_registered_call(server, NULL, NULL, NULL, NULL,
                                                  NULL, cc, cc, NULL));
   grpc_completion_queue_destroy(cc);
+  grpc_server_destroy(server);
 }
 
 void test_bind_server_twice(void) {
diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c
index d408374..6509cc5 100644
--- a/test/core/util/reconnect_server.c
+++ b/test/core/util/reconnect_server.c
@@ -71,6 +71,7 @@
 }
 
 static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
+                       grpc_pollset *accepting_pollset,
                        grpc_tcp_server_acceptor *acceptor) {
   char *peer;
   char *last_colon;
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc
index 0e43d4e..66225ff 100644
--- a/test/cpp/common/auth_property_iterator_test.cc
+++ b/test/cpp/common/auth_property_iterator_test.cc
@@ -38,7 +38,7 @@
 #include "test/cpp/util/string_ref_helper.h"
 
 extern "C" {
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
 }
 
 using ::grpc::testing::ToString;
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 0673613..b131452 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -38,7 +38,7 @@
 #include "test/cpp/util/string_ref_helper.h"
 
 extern "C" {
-#include "src/core/lib/security/security_context.h"
+#include "src/core/lib/security/context/security_context.h"
 }
 
 using grpc::testing::ToString;
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index e3408bf..f52aa52 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -48,7 +48,7 @@
 #include <grpc/support/time.h>
 #include <gtest/gtest.h>
 
-#include "src/core/lib/security/credentials.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc
index 02043a8..2c05db3 100644
--- a/test/cpp/end2end/hybrid_end2end_test.cc
+++ b/test/cpp/end2end/hybrid_end2end_test.cc
@@ -207,6 +207,9 @@
     ServerBuilder builder;
     builder.AddListeningPort(server_address_.str(),
                              grpc::InsecureServerCredentials());
+    // Always add a sync unimplemented service: we rely on having at least one
+    // synchronous method to get a listening cq
+    builder.RegisterService(&unimplemented_service_);
     builder.RegisterService(service1);
     if (service2) {
       builder.RegisterService(service2);
@@ -216,7 +219,7 @@
     }
     // Create a separate cq for each potential handler.
     for (int i = 0; i < 5; i++) {
-      cqs_.push_back(builder.AddCompletionQueue());
+      cqs_.push_back(builder.AddCompletionQueue(false));
     }
     server_ = builder.BuildAndStart();
   }
@@ -252,6 +255,7 @@
     EchoRequest send_request;
     EchoResponse recv_response;
     ClientContext cli_ctx;
+    cli_ctx.set_fail_fast(false);
     send_request.set_message("Hello");
     Status recv_status = stub_->Echo(&cli_ctx, send_request, &recv_response);
     EXPECT_EQ(send_request.message(), recv_response.message());
@@ -265,6 +269,7 @@
     EchoRequest send_request;
     EchoResponse recv_response;
     ClientContext cli_ctx;
+    cli_ctx.set_fail_fast(false);
     send_request.set_message("Hello");
     Status recv_status = stub->Echo(&cli_ctx, send_request, &recv_response);
     EXPECT_EQ(send_request.message() + "_dup", recv_response.message());
@@ -276,6 +281,7 @@
     EchoResponse recv_response;
     grpc::string expected_message;
     ClientContext cli_ctx;
+    cli_ctx.set_fail_fast(false);
     send_request.set_message("Hello");
     auto stream = stub_->RequestStream(&cli_ctx, &recv_response);
     for (int i = 0; i < 5; i++) {
@@ -292,6 +298,7 @@
     EchoRequest request;
     EchoResponse response;
     ClientContext context;
+    context.set_fail_fast(false);
     request.set_message("hello");
 
     auto stream = stub_->ResponseStream(&context, request);
@@ -311,6 +318,7 @@
     EchoRequest request;
     EchoResponse response;
     ClientContext context;
+    context.set_fail_fast(false);
     grpc::string msg("hello");
 
     auto stream = stub_->BidiStream(&context);
@@ -338,6 +346,7 @@
     EXPECT_TRUE(s.ok());
   }
 
+  grpc::testing::UnimplementedService::Service unimplemented_service_;
   std::vector<std::unique_ptr<ServerCompletionQueue> > cqs_;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
   std::unique_ptr<Server> server_;
diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc
index 87e3709..8a74621 100644
--- a/test/cpp/end2end/server_builder_plugin_test.cc
+++ b/test/cpp/end2end/server_builder_plugin_test.cc
@@ -189,6 +189,7 @@
   void StartServer() {
     grpc::string server_address = "localhost:" + to_string(port_);
     builder_->AddListeningPort(server_address, InsecureServerCredentials());
+    cq_ = builder_->AddCompletionQueue();
     server_ = builder_->BuildAndStart();
     EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
   }
@@ -206,6 +207,12 @@
     EXPECT_TRUE(plugin != nullptr);
     EXPECT_TRUE(plugin->init_server_is_called());
     EXPECT_TRUE(plugin->finish_is_called());
+    server_->Shutdown();
+    void* tag;
+    bool ok;
+    cq_->Shutdown();
+    while (cq_->Next(&tag, &ok))
+      ;
   }
 
   string to_string(const int number) {
@@ -218,6 +225,7 @@
   std::shared_ptr<Channel> channel_;
   std::unique_ptr<ServerBuilder> builder_;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+  std::unique_ptr<ServerCompletionQueue> cq_;
   std::unique_ptr<Server> server_;
   TestServiceImpl service_;
   int port_;
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index c8b1e50..c171969 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -97,30 +97,25 @@
   snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
            FLAGS_server_port);
 
+  std::shared_ptr<CallCredentials> creds;
   if (test_case == "compute_engine_creds") {
-    std::shared_ptr<CallCredentials> creds;
     GPR_ASSERT(FLAGS_use_tls);
     creds = GoogleComputeEngineCredentials();
-    return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
+    GPR_ASSERT(creds);
   } else if (test_case == "jwt_token_creds") {
-    std::shared_ptr<CallCredentials> creds;
     GPR_ASSERT(FLAGS_use_tls);
     grpc::string json_key = GetServiceAccountJsonKey();
     std::chrono::seconds token_lifetime = std::chrono::hours(1);
     creds =
         ServiceAccountJWTAccessCredentials(json_key, token_lifetime.count());
-    return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
+    GPR_ASSERT(creds);
   } else if (test_case == "oauth2_auth_token") {
     grpc::string raw_token = GetOauth2AccessToken();
-    std::shared_ptr<CallCredentials> creds = AccessTokenCredentials(raw_token);
-    return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
-  } else {
-    return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca);
+    creds = AccessTokenCredentials(raw_token);
+    GPR_ASSERT(creds);
   }
+  return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls,
+                           !FLAGS_use_test_ca, creds);
 }
 
 }  // namespace testing
diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc
index cc304f2..c8c2215 100644
--- a/test/cpp/interop/metrics_client.cc
+++ b/test/cpp/interop/metrics_client.cc
@@ -42,13 +42,15 @@
 #include "test/cpp/util/metrics_server.h"
 #include "test/cpp/util/test_config.h"
 
-DEFINE_string(metrics_server_address, "",
+int kDeadlineSecs = 10;
+
+DEFINE_string(metrics_server_address, "localhost:8081",
               "The metrics server addresses in the fomrat <hostname>:<port>");
+DEFINE_int32(deadline_secs, kDeadlineSecs,
+             "The deadline (in seconds) for RCP call");
 DEFINE_bool(total_only, false,
             "If true, this prints only the total value of all gauges");
 
-int kDeadlineSecs = 10;
-
 using grpc::testing::EmptyMessage;
 using grpc::testing::GaugeResponse;
 using grpc::testing::MetricsService;
@@ -56,12 +58,13 @@
 
 // Prints the values of all Gauges (unless total_only is set to 'true' in which
 // case this only prints the sum of all gauge values).
-bool PrintMetrics(std::unique_ptr<MetricsService::Stub> stub, bool total_only) {
+bool PrintMetrics(std::unique_ptr<MetricsService::Stub> stub, bool total_only,
+                  int deadline_secs) {
   grpc::ClientContext context;
   EmptyMessage message;
 
   std::chrono::system_clock::time_point deadline =
-      std::chrono::system_clock::now() + std::chrono::seconds(kDeadlineSecs);
+      std::chrono::system_clock::now() + std::chrono::seconds(deadline_secs);
 
   context.set_deadline(deadline);
 
@@ -108,7 +111,8 @@
   std::shared_ptr<grpc::Channel> channel(grpc::CreateChannel(
       FLAGS_metrics_server_address, grpc::InsecureChannelCredentials()));
 
-  if (!PrintMetrics(MetricsService::NewStub(channel), FLAGS_total_only)) {
+  if (!PrintMetrics(MetricsService::NewStub(channel), FLAGS_total_only,
+                    FLAGS_deadline_secs)) {
     return 1;
   }
 
diff --git a/test/cpp/qps/async_streaming_ping_pong_test.cc b/test/cpp/qps/async_streaming_ping_pong_test.cc
deleted file mode 100644
index 4b6bae0..0000000
--- a/test/cpp/qps/async_streaming_ping_pong_test.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunAsyncStreamingPingPong() {
-  gpr_log(GPR_INFO, "Running Async Streaming Ping Pong");
-
-  ClientConfig client_config;
-  client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1);
-  client_config.set_client_channels(1);
-  client_config.set_async_client_threads(1);
-  client_config.set_rpc_type(STREAMING);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(ASYNC_SERVER);
-  server_config.set_async_server_threads(1);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportLatency(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunAsyncStreamingPingPong();
-  return 0;
-}
diff --git a/test/cpp/qps/async_unary_ping_pong_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc
deleted file mode 100644
index 571a8b7..0000000
--- a/test/cpp/qps/async_unary_ping_pong_test.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunAsyncUnaryPingPong() {
-  gpr_log(GPR_INFO, "Running Async Unary Ping Pong");
-
-  ClientConfig client_config;
-  client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1);
-  client_config.set_client_channels(1);
-  client_config.set_async_client_threads(1);
-  client_config.set_rpc_type(UNARY);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(ASYNC_SERVER);
-  server_config.set_async_server_threads(1);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportLatency(*result);
-}
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunAsyncUnaryPingPong();
-  return 0;
-}
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 175529f..2a89eb8 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -38,6 +38,7 @@
 #include <mutex>
 #include <vector>
 
+#include <grpc++/channel.h>
 #include <grpc++/support/byte_buffer.h>
 #include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/slice.h>
@@ -315,6 +316,10 @@
           target, config.security_params().server_host_override(),
           config.has_security_params(), !config.security_params().use_test_ca(),
           std::shared_ptr<CallCredentials>(), args);
+      gpr_log(GPR_INFO, "Connecting to %s", target.c_str());
+      GPR_ASSERT(channel_->WaitForConnected(
+          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                       gpr_time_from_seconds(30, GPR_TIMESPAN))));
       stub_ = create_stub(channel_);
     }
     Channel* get_channel() { return channel_.get(); }
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
index 6b3329b..34b8151 100755
--- a/test/cpp/qps/gen_build_yaml.py
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -44,8 +44,29 @@
 import performance.scenario_config as scenario_config
 
 def _scenario_json_string(scenario_json):
+  # tweak parameters to get fast test times
+  scenario_json['warmup_seconds'] = 1
+  scenario_json['benchmark_seconds'] = 1
   return json.dumps(scenario_config.remove_nonproto_fields(scenario_json))
 
+def threads_of_type(scenario_json, path):
+  d = scenario_json
+  for el in path.split('/'):
+    if el not in d:
+      return 0
+    d = d[el]
+  return d
+
+def guess_cpu(scenario_json):
+  client = threads_of_type(scenario_json, 'client_config/async_client_threads')
+  server = threads_of_type(scenario_json, 'server_config/async_server_threads')
+  # make an arbitrary guess if set to auto-detect
+  # about the size of the jenkins instances we have for unit tests
+  if client == 0: client = 8
+  if server == 0: server = 8
+  return (scenario_json['num_clients'] * client +
+          scenario_json['num_servers'] * server)
+
 print yaml.dump({
   'tests': [
     {
@@ -59,7 +80,7 @@
       'language': 'c++',
       'boringssl': True,
       'defaults': 'boringssl',
-      'cpu_cost': 1000.0,
+      'cpu_cost': guess_cpu(scenario_json),
       'exclude_configs': []
     }
     for scenario_json in scenario_config.CXXLanguage().scenarios()
diff --git a/test/cpp/qps/generic_async_streaming_ping_pong_test.cc b/test/cpp/qps/generic_async_streaming_ping_pong_test.cc
deleted file mode 100644
index ea373ec..0000000
--- a/test/cpp/qps/generic_async_streaming_ping_pong_test.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunGenericAsyncStreamingPingPong() {
-  gpr_log(GPR_INFO, "Running Generic Async Streaming Ping Pong");
-
-  ClientConfig client_config;
-  client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1);
-  client_config.set_client_channels(1);
-  client_config.set_async_client_threads(1);
-  client_config.set_rpc_type(STREAMING);
-  client_config.mutable_load_params()->mutable_closed_loop();
-  auto bbuf = client_config.mutable_payload_config()->mutable_bytebuf_params();
-  bbuf->set_resp_size(0);
-  bbuf->set_req_size(0);
-
-  ServerConfig server_config;
-  server_config.set_server_type(ASYNC_GENERIC_SERVER);
-  server_config.set_async_server_threads(1);
-  *server_config.mutable_payload_config() = client_config.payload_config();
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportLatency(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunGenericAsyncStreamingPingPong();
-  return 0;
-}
diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc
index c3e72d9..f94ea0c 100644
--- a/test/cpp/qps/qps_test.cc
+++ b/test/cpp/qps/qps_test.cc
@@ -50,8 +50,8 @@
 
   ClientConfig client_config;
   client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1000);
-  client_config.set_client_channels(8);
+  client_config.set_outstanding_rpcs_per_channel(100);
+  client_config.set_client_channels(64);
   client_config.set_async_client_threads(8);
   client_config.set_rpc_type(STREAMING);
   client_config.mutable_load_params()->mutable_closed_loop();
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 1234542..1eddb1d 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -131,10 +131,10 @@
     }
   }
   ~AsyncQpsServerTest() {
-    server_->Shutdown();
     for (auto ss = shutdown_state_.begin(); ss != shutdown_state_.end(); ++ss) {
       (*ss)->set_shutdown();
     }
+    server_->Shutdown();
     for (auto thr = threads_.begin(); thr != threads_.end(); thr++) {
       thr->join();
     }
diff --git a/test/cpp/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc
deleted file mode 100644
index 67c62f4..0000000
--- a/test/cpp/qps/sync_streaming_ping_pong_test.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunSynchronousStreamingPingPong() {
-  gpr_log(GPR_INFO, "Running Synchronous Streaming Ping Pong");
-
-  ClientConfig client_config;
-  client_config.set_client_type(SYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1);
-  client_config.set_client_channels(1);
-  client_config.set_rpc_type(STREAMING);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(SYNC_SERVER);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportLatency(*result);
-}
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunSynchronousStreamingPingPong();
-
-  return 0;
-}
diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc
deleted file mode 100644
index aa0c0c3..0000000
--- a/test/cpp/qps/sync_unary_ping_pong_test.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * Copyright 2015, 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 <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunSynchronousUnaryPingPong() {
-  gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong");
-
-  ClientConfig client_config;
-  client_config.set_client_type(SYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1);
-  client_config.set_client_channels(1);
-  client_config.set_rpc_type(UNARY);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(SYNC_SERVER);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPS(*result);
-  GetReporter()->ReportLatency(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc::testing::RunSynchronousUnaryPingPong();
-
-  return 0;
-}
diff --git a/third_party/protobuf b/third_party/protobuf
index a1938b2..3470b68 160000
--- a/third_party/protobuf
+++ b/third_party/protobuf
@@ -1 +1 @@
-Subproject commit a1938b2aa9ca86ce7ce50c27ff9737c1008d2a03
+Subproject commit 3470b6895aa659b7559ed678e029a5338e535f14
diff --git a/tools/README.md b/tools/README.md
index cb6c22d..d142d4a 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -1,6 +1,6 @@
 buildgen: Template renderer for our build system.
 
-distrib: Scripts to distribute language-specific packages.
+distrib: Scripts to distribute language-specific packages and other distribution-related helper scripts.
 
 dockerfile: Docker files to test gRPC.
 
diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile
index 43b2a0c..70a32c5 100644
--- a/tools/dockerfile/test/sanity/Dockerfile
+++ b/tools/dockerfile/test/sanity/Dockerfile
@@ -27,7 +27,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-FROM debian:jessie
+FROM ubuntu:15.10
 
 # Install Git and basic packages.
 RUN apt-get update && apt-get install -y \
@@ -77,9 +77,8 @@
 
 #======================================
 # More sanity test dependencies (bazel)
-RUN echo "deb http://httpredir.debian.org/debian jessie-backports main" >   /etc/apt/sources.list.d/backports.list
-RUN apt-get update
-RUN apt-get -t jessie-backports install -y openjdk-8-jdk
+RUN apt-get install -y openjdk-8-jdk
+# TOOD(jtattermusch): pin the bazel version
 RUN git clone https://github.com/bazelbuild/bazel.git /bazel
 RUN cd /bazel && ./compile.sh
 RUN ln -s /bazel/output/bazel /bin/
@@ -88,7 +87,6 @@
 # Docker "inception"
 # Note this is quite the ugly hack.
 # This makes sure that the docker binary we inject has its dependencies.
-RUN apt-get install libsystemd-journal0
 RUN curl https://get.docker.com/ | sh
 RUN apt-get remove --purge -y docker-engine
 
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index eb89f82..4a1ed90 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -807,7 +807,6 @@
 src/core/lib/iomgr/closure.h \
 src/core/lib/iomgr/endpoint.h \
 src/core/lib/iomgr/endpoint_pair.h \
-src/core/lib/iomgr/ev_poll_and_epoll_posix.h \
 src/core/lib/iomgr/ev_poll_posix.h \
 src/core/lib/iomgr/ev_posix.h \
 src/core/lib/iomgr/exec_ctx.h \
@@ -886,15 +885,24 @@
 src/core/ext/transport/chttp2/transport/timeout_encoding.h \
 src/core/ext/transport/chttp2/transport/varint.h \
 src/core/ext/transport/chttp2/alpn/alpn.h \
-src/core/lib/security/auth_filters.h \
-src/core/lib/security/b64.h \
-src/core/lib/security/credentials.h \
-src/core/lib/security/handshake.h \
-src/core/lib/security/json_token.h \
-src/core/lib/security/jwt_verifier.h \
-src/core/lib/security/secure_endpoint.h \
-src/core/lib/security/security_connector.h \
-src/core/lib/security/security_context.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/handshake.h \
+src/core/lib/security/transport/secure_endpoint.h \
+src/core/lib/security/transport/security_connector.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 \
@@ -947,7 +955,6 @@
 src/core/lib/iomgr/endpoint.c \
 src/core/lib/iomgr/endpoint_pair_posix.c \
 src/core/lib/iomgr/endpoint_pair_windows.c \
-src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
 src/core/lib/iomgr/ev_poll_posix.c \
 src/core/lib/iomgr/ev_posix.c \
 src/core/lib/iomgr/exec_ctx.c \
@@ -1037,20 +1044,28 @@
 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/security/b64.c \
-src/core/lib/security/client_auth_filter.c \
-src/core/lib/security/credentials.c \
-src/core/lib/security/credentials_metadata.c \
-src/core/lib/security/credentials_posix.c \
-src/core/lib/security/credentials_win32.c \
-src/core/lib/security/google_default_credentials.c \
-src/core/lib/security/handshake.c \
-src/core/lib/security/json_token.c \
-src/core/lib/security/jwt_verifier.c \
-src/core/lib/security/secure_endpoint.c \
-src/core/lib/security/security_connector.c \
-src/core/lib/security/security_context.c \
-src/core/lib/security/server_auth_filter.c \
+src/core/lib/security/context/security_context.c \
+src/core/lib/security/credentials/composite/composite_credentials.c \
+src/core/lib/security/credentials/credentials.c \
+src/core/lib/security/credentials/credentials_metadata.c \
+src/core/lib/security/credentials/fake/fake_credentials.c \
+src/core/lib/security/credentials/google_default/credentials_posix.c \
+src/core/lib/security/credentials/google_default/credentials_win32.c \
+src/core/lib/security/credentials/google_default/google_default_credentials.c \
+src/core/lib/security/credentials/iam/iam_credentials.c \
+src/core/lib/security/credentials/jwt/json_token.c \
+src/core/lib/security/credentials/jwt/jwt_credentials.c \
+src/core/lib/security/credentials/jwt/jwt_verifier.c \
+src/core/lib/security/credentials/oauth2/oauth2_credentials.c \
+src/core/lib/security/credentials/plugin/plugin_credentials.c \
+src/core/lib/security/credentials/ssl/ssl_credentials.c \
+src/core/lib/security/transport/client_auth_filter.c \
+src/core/lib/security/transport/handshake.c \
+src/core/lib/security/transport/secure_endpoint.c \
+src/core/lib/security/transport/security_connector.c \
+src/core/lib/security/transport/server_auth_filter.c \
+src/core/lib/security/util/b64.c \
+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 \
diff --git a/tools/gcp/stress_test/run_client.py b/tools/gcp/stress_test/run_client.py
index 2004bf6..51ada68 100755
--- a/tools/gcp/stress_test/run_client.py
+++ b/tools/gcp/stress_test/run_client.py
@@ -133,12 +133,15 @@
     details = 'Logfile: %s' % logfile_name
     logfile = open(logfile_name, 'w')
 
+  metrics_cmd = metrics_client_cmd + [x
+                                      for x in metrics_client_args_str.split()]
+  stress_cmd = stress_client_cmd + [x for x in args_str.split()]
+
+  details = '%s, Metrics command: %s, Stress client command: %s' % (
+      details, str(metrics_cmd), str(stress_cmd))
   # Update status that the test is starting (in the status table)
   bq_helper.insert_summary_row(EventType.STARTING, details)
 
-  metrics_cmd = metrics_client_cmd + [x for x in metrics_client_args_str.split()]
-  stress_cmd = stress_client_cmd + [x for x in args_str.split()]
-
   print 'Launching process %s ...' % stress_cmd
   stress_p = subprocess.Popen(args=stress_cmd,
                               stdout=logfile,
@@ -147,6 +150,7 @@
   qps_history = [1, 1, 1]  # Maintain the last 3 qps readings
   qps_history_idx = 0  # Index into the qps_history list
 
+  is_running_status_written = False
   is_error = False
   while True:
     # Check if stress_client is still running. If so, collect metrics and upload
@@ -165,6 +169,10 @@
       print details
       break
 
+    if not is_running_status_written:
+      bq_helper.insert_summary_row(EventType.RUNNING, '')
+      is_running_status_written = True
+
     # Stress client still running. Get metrics
     qps = _get_qps(metrics_cmd)
     qps_recorded_at = datetime.datetime.now().isoformat()
diff --git a/tools/gcp/stress_test/run_server.py b/tools/gcp/stress_test/run_server.py
index a666ae2..8f47e42 100755
--- a/tools/gcp/stress_test/run_server.py
+++ b/tools/gcp/stress_test/run_server.py
@@ -106,16 +106,22 @@
     logfile = open(logfile_name, 'w')
     details = 'Logfile: %s' % logfile_name
 
+  stress_cmd = stress_server_cmd + [x for x in args_str.split()]
+
+  details = '%s, Stress server command: %s' % (details, str(stress_cmd))
   # Update status that the test is starting (in the status table)
   bq_helper.insert_summary_row(EventType.STARTING, details)
 
-  stress_cmd = stress_server_cmd + [x for x in args_str.split()]
-
   print 'Launching process %s ...' % stress_cmd
   stress_p = subprocess.Popen(args=stress_cmd,
                               stdout=logfile,
                               stderr=subprocess.STDOUT)
 
+  # Update the status to running if subprocess.Popen launched the server
+  if stress_p.poll() is None:
+    bq_helper.insert_summary_row(EventType.RUNNING, '')
+
+  # Wait for the server process to terminate
   returncode = stress_p.wait()
 
   if will_run_forever == '1' or returncode != 0:
diff --git a/tools/gcp/stress_test/stress_test_utils.py b/tools/gcp/stress_test/stress_test_utils.py
index 19d59c0..b821fc8 100755
--- a/tools/gcp/stress_test/stress_test_utils.py
+++ b/tools/gcp/stress_test/stress_test_utils.py
@@ -46,6 +46,7 @@
 
 class EventType:
   STARTING = 'STARTING'
+  RUNNING = 'RUNNING'
   SUCCESS = 'SUCCESS'
   FAILURE = 'FAILURE'
 
@@ -195,11 +196,11 @@
         ('image_type', 'STRING', 'Client or Server?'),
         ('pod_name', 'STRING', 'GKE pod hosting this image'),
         ('event_date', 'STRING', 'The date of this event'),
-        ('event_type', 'STRING', 'STARTED/SUCCESS/FAILURE'),
+        ('event_type', 'STRING', 'STARTING/RUNNING/SUCCESS/FAILURE'),
         ('details', 'STRING', 'Any other relevant details')
     ]
-    desc = ('The table that contains START/SUCCESS/FAILURE events for '
-            ' the stress test clients and servers')
+    desc = ('The table that contains STARTING/RUNNING/SUCCESS/FAILURE events '
+            'for the stress test clients and servers')
     return bq_utils.create_table(self.bq, self.project_id, self.dataset_id,
                                  self.summary_table_id, summary_table_schema,
                                  desc)
diff --git a/tools/jenkins/run_full_performance.sh b/tools/jenkins/run_full_performance.sh
new file mode 100755
index 0000000..3feda86
--- /dev/null
+++ b/tools/jenkins/run_full_performance.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+# Copyright 2015, 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.
+#
+# This script is invoked by Jenkins and runs full performance test suite.
+set -ex
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../..
+
+# run 8core client vs 8core server
+tools/run_tests/run_performance_tests.py \
+    -l c++ csharp node ruby java python go \
+    --netperf \
+    --category all \
+    --bq_result_table performance_test.performance_experiment \
+    --remote_worker_host grpc-performance-server-8core grpc-performance-client-8core grpc-performance-client2-8core \
+    || EXIT_CODE=1
+
+# scalability with 32cores (and upload to a different BQ table)
+tools/run_tests/run_performance_tests.py \
+    -l c++ java csharp go \
+    --netperf \
+    --category scalable \
+    --bq_result_table performance_test.performance_experiment_32core \
+    --remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \
+    || EXIT_CODE=1
+
+exit $EXIT_CODE
+
diff --git a/tools/run_tests/README.md b/tools/run_tests/README.md
new file mode 100644
index 0000000..dd727f4
--- /dev/null
+++ b/tools/run_tests/README.md
@@ -0,0 +1,52 @@
+#Overview
+
+This directory contains scripts that facilitate building and running tests. We are using python scripts as entrypoint for our
+tests because that gives us the opportunity to run tests using the same commandline regardless of the platform you are using.
+
+#Unit tests (run_tests.py)
+
+Builds gRPC in given language and runs unit tests. Use `tools/run_tests/run_tests.py --help` for more help.
+
+######Example
+`tools/run_tests/run_tests.py -l csharp -c dbg`
+
+######Useful options (among many others)
+- `--use_docker` Builds a docker container containing all the prerequisites for given language and runs the tests under that container.
+- `--build_only` Only build, do not run the tests.
+
+#Interop tests (run_interop_tests.py)
+
+Runs tests for cross-platform/cross-language interoperability. For more details, see [Interop tests descriptions](/doc/interop-test-descriptions.md)
+The script is also capable of running interop tests for grpc-java and grpc-go, using sources checked out alongside the ones of the grpc repository.
+
+######Example
+`tools/run_tests/run_interop_tests.py -l csharp -s c++ --use_docker` (run interop tests with C# client and C++ server)
+
+#Performance benchmarks (run_performance_tests.py)
+
+Runs predefined benchmark scenarios for given languages. Besides the simple configuration of running all the scenarios locally,
+the script also supports orchestrating test runs with client and server running on different machines and uploading the results
+to BigQuery.
+
+######Example
+`tools/run_tests/run_peformance_tests.py -l c++ node`
+
+######Useful options
+- `--regex` use regex to select particular scenarios to run.
+
+#Stress tests (run_stress_tests.py)
+
+Runs modified interop tests clients and servers under heavy load for an extended period of time to discover potential stability issues.
+The tests are internally using Kubernetes to run the client and server on GKE and upload statistics to BigQuery.
+
+`tools/run_tests/stress_test/run_on_gke.py --gcp_project_id=<google-cloud-platform-project-id> --config_file=<path-to-config-file>` 
+
+The directory `tools/run_tests/stress_test/configs/` contains the config files for several scenarios
+
+#Artifacts & Packages (task_runner.py)
+
+A generalized framework for running predefined tasks based on their labels. We use this to building binary artifacts & distrib packages and testing them)
+
+######Example
+`tools/run_tests/task_runner.py -f python artifact linux x64` (build tasks with labels `python`, `artifact`, `linux`, and `x64`)
+
diff --git a/tools/run_tests/configs.json b/tools/run_tests/configs.json
index bcc4118..b0839ef 100644
--- a/tools/run_tests/configs.json
+++ b/tools/run_tests/configs.json
@@ -57,7 +57,7 @@
   {
     "config": "ubsan", 
     "environ": {
-      "UBSAN_OPTIONS": "print_stacktrace=1"
+      "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1"
     }, 
     "timeout_multiplier": 1.5
   }, 
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
index 77b158f..b55d728 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -34,6 +34,7 @@
 BENCHMARK_SECONDS=30
 
 SMOKETEST='smoketest'
+SCALABLE='scalable'
 
 SECURE_SECARGS = {'use_test_ca': True,
                   'server_host_override': 'foo.test.google.fr'}
@@ -181,7 +182,7 @@
     # TODO(ctiller): add 70% load latency test
     for secure in [True, False]:
       secstr = 'secure' if secure else 'insecure'
-      smoketest_categories = [SMOKETEST] if secure else None
+      smoketest_categories = [SMOKETEST] if secure else []
 
       yield _ping_pong_scenario(
           'cpp_generic_async_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
@@ -214,20 +215,21 @@
           client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
-          categories=smoketest_categories)
+          categories=smoketest_categories+[SCALABLE])
 
       yield _ping_pong_scenario(
           'cpp_protobuf_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
           unconstrained_client='async',
-          secure=secure)
+          secure=secure,
+          categories=[SCALABLE])
 
       yield _ping_pong_scenario(
           'cpp_generic_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
           secure=secure,
-          categories=smoketest_categories)
+          categories=smoketest_categories+[SCALABLE])
 
       yield _ping_pong_scenario(
           'cpp_generic_async_streaming_qps_one_server_core_%s' % secstr, rpc_type='STREAMING',
@@ -275,12 +277,13 @@
         'csharp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
         client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
         unconstrained_client='async',
-        categories=[SMOKETEST])
+        categories=[SMOKETEST,SCALABLE])
 
     yield _ping_pong_scenario(
         'csharp_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
         client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
-        unconstrained_client='async')
+        unconstrained_client='async',
+        categories=[SCALABLE])
 
     yield _ping_pong_scenario(
         'csharp_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
@@ -296,17 +299,20 @@
     yield _ping_pong_scenario(
         'csharp_to_cpp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
         client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
-        unconstrained_client='async', server_language='c++')
+        unconstrained_client='async', server_language='c++',
+        categories=[SCALABLE])
 
     yield _ping_pong_scenario(
         'csharp_to_cpp_protobuf_sync_to_async_unary_qps_unconstrained', rpc_type='UNARY',
         client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
-        unconstrained_client='sync', server_language='c++')
+        unconstrained_client='sync', server_language='c++',
+        categories=[SCALABLE])
 
     yield _ping_pong_scenario(
         'cpp_to_csharp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
         client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
-        unconstrained_client='async', client_language='c++')
+        unconstrained_client='async', client_language='c++',
+        categories=[SCALABLE])
 
 
   def __str__(self):
@@ -487,7 +493,7 @@
   def scenarios(self):
     for secure in [True, False]:
       secstr = 'secure' if secure else 'insecure'
-      smoketest_categories = [SMOKETEST] if secure else None
+      smoketest_categories = [SMOKETEST] if secure else []
 
       yield _ping_pong_scenario(
           'java_generic_async_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
@@ -520,19 +526,21 @@
           client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
           unconstrained_client='async',
           secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
-          categories=smoketest_categories)
+          categories=smoketest_categories+[SCALABLE])
 
       yield _ping_pong_scenario(
           'java_protobuf_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
           unconstrained_client='async',
-          secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS)
+          secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
+          categories=[SCALABLE])
 
       yield _ping_pong_scenario(
           'java_generic_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
-          secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS)
+          secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
+          categories=[SCALABLE])
 
       yield _ping_pong_scenario(
           'java_generic_async_streaming_qps_one_server_core_%s' % secstr, rpc_type='STREAMING',
@@ -562,7 +570,7 @@
   def scenarios(self):
     for secure in [True, False]:
       secstr = 'secure' if secure else 'insecure'
-      smoketest_categories = [SMOKETEST] if secure else None
+      smoketest_categories = [SMOKETEST] if secure else []
 
       # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
       # but that's mostly because of lack of better name of the enum value. 
@@ -592,14 +600,15 @@
           client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
-          categories=smoketest_categories)
+          categories=smoketest_categories+[SCALABLE])
 
       # unconstrained_client='async' is intended (client uses goroutines)
       yield _ping_pong_scenario(
           'go_protobuf_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
           unconstrained_client='async',
-          secure=secure)
+          secure=secure,
+          categories=[SCALABLE])
 
       # unconstrained_client='async' is intended (client uses goroutines)
       # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
@@ -608,7 +617,8 @@
           'go_generic_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
           client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
           unconstrained_client='async', use_generic_payload=True,
-          secure=secure)
+          secure=secure,
+          categories=[SCALABLE])
 
       # TODO(jtattermusch): add scenarios go vs C++ 
 
diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py
index 181d62b..f037d0d 100755
--- a/tools/run_tests/run_performance_tests.py
+++ b/tools/run_tests/run_performance_tests.py
@@ -73,7 +73,6 @@
 
 def create_qpsworker_job(language, shortname=None,
                          port=10000, remote_host=None):
-  # TODO: support more languages
   cmdline = language.worker_cmdline() + ['--driver_port=%s' % port]
   if remote_host:
     user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
@@ -373,7 +372,7 @@
 argp.add_argument('--bq_result_table', default=None, type=str,
                   help='Bigquery "dataset.table" to upload results to.')
 argp.add_argument('--category',
-                  choices=['smoketest','all'],
+                  choices=['smoketest','all','scalable'],
                   default='all',
                   help='Select a category of tests to run.')
 argp.add_argument('--netperf',
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 65596de..0538dce 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -157,7 +157,7 @@
       'windows': ['all'],
       'mac': ['all'],
       'posix': ['all'],
-      'linux': ['poll', 'legacy']
+      'linux': ['poll'],
     }
     for target in binaries:
       polling_strategies = (POLLING_STRATEGIES[self.platform]
@@ -892,7 +892,7 @@
 
 language_make_options=[]
 if any(language.make_options() for language in languages):
-  if len(languages) != 1:
+  if not 'gcov' in args.config and len(languages) != 1:
     print 'languages with custom make options cannot be built simultaneously with other languages'
     sys.exit(1)
   else:
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 3b8d81b..6e858fa 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -45,7 +45,7 @@
  05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f)
  c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0)
  f8ac463766281625ad710900479130c7fcb4d63b third_party/nanopb (nanopb-0.3.4-29-gf8ac463)
- a1938b2aa9ca86ce7ce50c27ff9737c1008d2a03 third_party/protobuf (v3.0.0-beta-3-pre1)
+ 3470b6895aa659b7559ed678e029a5338e535f14 third_party/protobuf (v3.0.0-beta-2-441-g3470b68)
  50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
 EOF
 
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index ddfe2f0..1c476b7 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -1818,44 +1818,6 @@
       "grpc", 
       "grpc++", 
       "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "async_streaming_ping_pong_test", 
-    "src": [
-      "test/cpp/qps/async_streaming_ping_pong_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "async_unary_ping_pong_test", 
-    "src": [
-      "test/cpp/qps/async_unary_ping_pong_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
       "grpc_test_util"
     ], 
     "headers": [], 
@@ -2095,25 +2057,6 @@
       "grpc", 
       "grpc++", 
       "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "generic_async_streaming_ping_pong_test", 
-    "src": [
-      "test/cpp/qps/generic_async_streaming_ping_pong_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
       "grpc_test_util"
     ], 
     "headers": [], 
@@ -2463,26 +2406,6 @@
       "grpc_test_util", 
       "qps"
     ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "qps_test", 
-    "src": [
-      "test/cpp/qps/qps_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_config", 
-      "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
     "headers": [
       "test/cpp/qps/client.h", 
       "test/cpp/qps/server.h"
@@ -2741,44 +2664,6 @@
       "grpc", 
       "grpc++", 
       "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "sync_streaming_ping_pong_test", 
-    "src": [
-      "test/cpp/qps/sync_streaming_ping_pong_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util", 
-      "qps"
-    ], 
-    "headers": [], 
-    "language": "c++", 
-    "name": "sync_unary_ping_pong_test", 
-    "src": [
-      "test/cpp/qps/sync_unary_ping_pong_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
       "grpc_test_util"
     ], 
     "headers": [], 
@@ -5645,7 +5530,6 @@
       "src/core/lib/iomgr/closure.h", 
       "src/core/lib/iomgr/endpoint.h", 
       "src/core/lib/iomgr/endpoint_pair.h", 
-      "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", 
       "src/core/lib/iomgr/ev_poll_posix.h", 
       "src/core/lib/iomgr/ev_posix.h", 
       "src/core/lib/iomgr/exec_ctx.h", 
@@ -5746,8 +5630,6 @@
       "src/core/lib/iomgr/endpoint_pair.h", 
       "src/core/lib/iomgr/endpoint_pair_posix.c", 
       "src/core/lib/iomgr/endpoint_pair_windows.c", 
-      "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", 
-      "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", 
       "src/core/lib/iomgr/ev_poll_posix.c", 
       "src/core/lib/iomgr/ev_poll_posix.h", 
       "src/core/lib/iomgr/ev_posix.c", 
@@ -6059,15 +5941,24 @@
       "include/grpc/grpc_cronet.h", 
       "include/grpc/grpc_security.h", 
       "include/grpc/grpc_security_constants.h", 
-      "src/core/lib/security/auth_filters.h", 
-      "src/core/lib/security/b64.h", 
-      "src/core/lib/security/credentials.h", 
-      "src/core/lib/security/handshake.h", 
-      "src/core/lib/security/json_token.h", 
-      "src/core/lib/security/jwt_verifier.h", 
-      "src/core/lib/security/secure_endpoint.h", 
-      "src/core/lib/security/security_connector.h", 
-      "src/core/lib/security/security_context.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/handshake.h", 
+      "src/core/lib/security/transport/secure_endpoint.h", 
+      "src/core/lib/security/transport/security_connector.h", 
+      "src/core/lib/security/util/b64.h", 
+      "src/core/lib/security/util/json_util.h"
     ], 
     "language": "c", 
     "name": "grpc_secure", 
@@ -6076,29 +5967,46 @@
       "include/grpc/grpc_security.h", 
       "include/grpc/grpc_security_constants.h", 
       "src/core/lib/http/httpcli_security_connector.c", 
-      "src/core/lib/security/auth_filters.h", 
-      "src/core/lib/security/b64.c", 
-      "src/core/lib/security/b64.h", 
-      "src/core/lib/security/client_auth_filter.c", 
-      "src/core/lib/security/credentials.c", 
-      "src/core/lib/security/credentials.h", 
-      "src/core/lib/security/credentials_metadata.c", 
-      "src/core/lib/security/credentials_posix.c", 
-      "src/core/lib/security/credentials_win32.c", 
-      "src/core/lib/security/google_default_credentials.c", 
-      "src/core/lib/security/handshake.c", 
-      "src/core/lib/security/handshake.h", 
-      "src/core/lib/security/json_token.c", 
-      "src/core/lib/security/json_token.h", 
-      "src/core/lib/security/jwt_verifier.c", 
-      "src/core/lib/security/jwt_verifier.h", 
-      "src/core/lib/security/secure_endpoint.c", 
-      "src/core/lib/security/secure_endpoint.h", 
-      "src/core/lib/security/security_connector.c", 
-      "src/core/lib/security/security_connector.h", 
-      "src/core/lib/security/security_context.c", 
-      "src/core/lib/security/security_context.h", 
-      "src/core/lib/security/server_auth_filter.c", 
+      "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_posix.c", 
+      "src/core/lib/security/credentials/google_default/credentials_win32.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/handshake.c", 
+      "src/core/lib/security/transport/handshake.h", 
+      "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/server_auth_filter.c", 
+      "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/security/util/json_util.h", 
       "src/core/lib/surface/init_secure.c"
     ], 
     "third_party": false, 
diff --git a/tools/run_tests/stress_test/configs/csharp.json b/tools/run_tests/stress_test/configs/csharp.json
index 587e155..c438e08 100644
--- a/tools/run_tests/stress_test/configs/csharp.json
+++ b/tools/run_tests/stress_test/configs/csharp.json
@@ -10,7 +10,7 @@
     "baseTemplates": {
       "default": {
         "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
-        "pollIntervalSecs": 60,
+        "pollIntervalSecs": 100,
         "clientArgs": {
           "num_channels_per_server":5,
           "num_stubs_per_channel":10,
@@ -20,7 +20,8 @@
         "metricsPort": 8081,
         "metricsArgs": {
           "metrics_server_address": "localhost:8081",
-          "total_only": "true"
+          "total_only": "true",
+          "deadline_secs": 60
         }
       }
     },
@@ -78,7 +79,7 @@
 
   "globalSettings": {
     "buildDockerImages": true,
-    "pollIntervalSecs": 60,
+    "pollIntervalSecs": 100,
     "testDurationSecs": 7200,
     "kubernetesProxyPort": 8009,
     "datasetIdNamePrefix": "stress_test_csharp",
diff --git a/tools/run_tests/stress_test/configs/java.json b/tools/run_tests/stress_test/configs/java.json
index b7c6d8b..92af63c 100644
--- a/tools/run_tests/stress_test/configs/java.json
+++ b/tools/run_tests/stress_test/configs/java.json
@@ -10,7 +10,7 @@
     "baseTemplates": {
       "default": {
         "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
-        "pollIntervalSecs": 60,
+        "pollIntervalSecs": 100,
         "clientArgs": {
           "num_channels_per_server":5,
           "num_stubs_per_channel":10,
@@ -20,7 +20,8 @@
         "metricsPort": 8081,
         "metricsArgs": {
           "metrics_server_address": "localhost:8081",
-          "total_only": "true"
+          "total_only": "true",
+          "deadline_secs": 60
         },
         "env": {
           "STRESSTEST_CLIENT_OPTS":"-Xmx3g -Xms3g -XX:NewSize=1500m -XX:MaxNewSize=1500m -XX:+UseConcMarkSweepGC"
@@ -85,7 +86,7 @@
 
   "globalSettings": {
     "buildDockerImages": true,
-    "pollIntervalSecs": 60,
+    "pollIntervalSecs": 100,
     "testDurationSecs": 7200,
     "kubernetesProxyPort": 8008,
     "datasetIdNamePrefix": "stress_test_java",
diff --git a/tools/run_tests/stress_test/print_summary.py b/tools/run_tests/stress_test/print_summary.py
new file mode 100755
index 0000000..cb1a339
--- /dev/null
+++ b/tools/run_tests/stress_test/print_summary.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python2.7
+# 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.
+import argparse
+import os
+import sys
+
+stress_test_utils_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../../gcp/stress_test'))
+sys.path.append(stress_test_utils_dir)
+from stress_test_utils import BigQueryHelper
+
+argp = argparse.ArgumentParser(
+    description='Print summary tables',
+    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+argp.add_argument('--gcp_project_id',
+                  required=True,
+                  help='The Google Cloud Platform Project Id')
+argp.add_argument('--dataset_id', type=str, required=True)
+argp.add_argument('--run_id', type=str, required=True)
+argp.add_argument('--summary_table_id', type=str, default='summary')
+argp.add_argument('--qps_table_id', type=str, default='qps')
+argp.add_argument('--summary_only', action='store_true', default=True)
+
+if __name__ == '__main__':
+  args = argp.parse_args()
+  bq_helper = BigQueryHelper(args.run_id, '', '', args.gcp_project_id,
+                             args.dataset_id, args.summary_table_id,
+                             args.qps_table_id)
+  bq_helper.initialize()
+  if not args.summary_only:
+    bq_helper.print_qps_records()
+  bq_helper.print_summary_records()
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 4f11ceb..850f947 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -1944,44 +1944,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "async_streaming_ping_pong_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "async_unary_ping_pong_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix", 
       "windows"
     ], 
@@ -2232,25 +2194,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "generic_async_streaming_ping_pong_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix", 
       "windows"
     ], 
@@ -2394,25 +2337,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 10, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "qps_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix", 
       "windows"
     ], 
@@ -2554,44 +2478,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "sync_streaming_ping_pong_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c++", 
-    "name": "sync_unary_ping_pong_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix", 
       "windows"
     ], 
@@ -23022,7 +22908,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23031,7 +22917,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23048,7 +22934,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23057,7 +22943,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23074,7 +22960,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23083,7 +22969,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23100,7 +22986,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23109,7 +22995,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23126,7 +23012,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23135,7 +23021,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23152,7 +23038,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23161,7 +23047,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23178,7 +23064,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23187,7 +23073,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23204,7 +23090,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23213,7 +23099,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 1, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23230,7 +23116,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23239,7 +23125,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23256,7 +23142,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23265,7 +23151,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23282,7 +23168,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23291,7 +23177,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23308,7 +23194,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
+      "'{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 1}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23317,7 +23203,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 2, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23334,7 +23220,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23343,7 +23229,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23360,7 +23246,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23369,7 +23255,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23386,7 +23272,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23395,7 +23281,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 8, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23412,7 +23298,7 @@
   {
     "args": [
       "--scenario_json", 
-      "'{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 5, \"benchmark_seconds\": 30, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
+      "'{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 1, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}'"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -23421,7 +23307,7 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 1000.0, 
+    "cpu_cost": 1, 
     "defaults": "boringssl", 
     "exclude_configs": [], 
     "flaky": false, 
@@ -23454,6 +23340,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/001ea98069c10f808c281da9bbdd84cc05c3bad1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/01.bin"
     ], 
     "ci_platforms": [
@@ -23488,6 +23391,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/01f52e31dfffdab89d83acd39925c3dd81baa76f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/02.bin"
     ], 
     "ci_platforms": [
@@ -23556,6 +23476,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/02c3cf8d52fbc43f89b5f516a17cea23b68fc8d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/03.bin"
     ], 
     "ci_platforms": [
@@ -23590,6 +23527,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/032744b59cafd3320cc932ad39926a9bc92f589e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0385c7b41263419e25a4342fbfc44fbd65eb2ed5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin"
     ], 
     "ci_platforms": [
@@ -23675,6 +23646,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/04d93c9df413717f71abd091592b5238afb799e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/04e01f399f194434b2b724877df64828e8f52c14"
     ], 
     "ci_platforms": [
@@ -23811,6 +23799,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/064d50aee4416ccf32f4e4fe7b770b7802265ffe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/066e7fcb68e83b432c414f63f6de73e5f5099e49"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/067298a97640cc5e212647864d21bc1fa6bb7e75"
     ], 
     "ci_platforms": [
@@ -23828,6 +23850,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06c714e289673cf982ce2ac0670707a15f2ac5ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin"
     ], 
     "ci_platforms": [
@@ -23862,6 +23901,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/071247b8fddda8aa520d9142c89039fbf8bf6cee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07674d39538e07c29342cb2ee8856bc71fc06638"
     ], 
     "ci_platforms": [
@@ -23913,6 +23969,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07cb3b9baca1bbcce2e199e551073ba2fdd4e05c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07cc8b298d1502d0c30f3f160871e66e5a1f3fe1"
     ], 
     "ci_platforms": [
@@ -23930,6 +24003,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07fa2b6ed650d436f423adcccfcbe63ce6253de0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/08.bin"
     ], 
     "ci_platforms": [
@@ -23947,6 +24037,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/081e3248dfca2b32837c4738daee3a4698caaf15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0"
     ], 
     "ci_platforms": [
@@ -23964,6 +24071,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/088bf259e854abd9508d91b23983737f8e9e242c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/09.bin"
     ], 
     "ci_platforms": [
@@ -23998,6 +24122,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb"
     ], 
     "ci_platforms": [
@@ -24066,6 +24207,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0af5adf68560b3a7036ad23af62e4f9749eca690"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0b.bin"
     ], 
     "ci_platforms": [
@@ -24117,6 +24292,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0becc6ede499ddc452fd4e6c3c0413a1107a8373"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin"
     ], 
     "ci_platforms": [
@@ -24134,6 +24326,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0c531e03e56a5cf48bdd531a8c11a19e4a3b0aeb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0c65733bc09e8527347e20f5c876c5b64570d423"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0c7b763d22885462527123656fa17af7520fc55d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin"
     ], 
     "ci_platforms": [
@@ -24168,6 +24411,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0d8bd296d63a5aca5f80d7a7d00387048babda36"
     ], 
     "ci_platforms": [
@@ -24185,6 +24445,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d993b34021ec088f1aa3e5acdd98089b4104b07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0d9d8241c5568fea586d21f91ae1891dac31ba24"
     ], 
     "ci_platforms": [
@@ -24202,6 +24479,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0def53b5575cc6ab2fbbd17e2bc6a24de9656f84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin"
     ], 
     "ci_platforms": [
@@ -24236,6 +24530,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0e2ddbe92c08eb9ad3cbee1d0db2264baaca12df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0ea509d249ae28faba8980aacb972c7ea28d3fd5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin"
     ], 
     "ci_platforms": [
@@ -24253,6 +24581,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0f16eeeecdebcb59022bda5a0972d1b3429648fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0f2831e0f73521a0991e11115c16847afca16bb3"
     ], 
     "ci_platforms": [
@@ -24270,6 +24615,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0f81830560dbb9c6d3889b5d581b918c6cade65f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0fa216ec645b3973b5e6d28baedd5acc1542e69e"
     ], 
     "ci_platforms": [
@@ -24304,6 +24666,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/105d9784648fe2d6c22fbefa69c9a26fff1c6481"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f"
     ], 
     "ci_platforms": [
@@ -24321,6 +24700,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/11153bfeee3cdede86a52151dbb939c3ffee48ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/113c1d1bac15d550124f1ffb9012c32755adf27f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/11759723c597e6806f8873e5062d31516cdb97ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/119410315423e5f37919886ced7f03235e5792aa"
     ], 
     "ci_platforms": [
@@ -24389,6 +24819,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12abf5dcf2aba770f7b94ce5d96d7a8565a9aa19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12b904b97ed234fa45073b4e346ebe3211558528"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12c00ed8945bdae03f03142cb964a47ea0c5786e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/12ef45f6beba92677a2a7508fc5e1bfef30ded66"
     ], 
     "ci_platforms": [
@@ -24406,6 +24887,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/12f977ee18a7499d18a503a47e71b4f241052640"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/130c41e2dd87c36b4079c8e5bd380dbe3e0a2b38"
     ], 
     "ci_platforms": [
@@ -24457,6 +24955,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/145acf7c03a0bc6c4a40d710ba5813b9f28efe2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/149044286608a7945721c61f12196bebd5adb2ee"
     ], 
     "ci_platforms": [
@@ -24474,6 +24989,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/14ccbe1d9d7302d642e51ede3d4d846e85310fc2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/157586c7c0ba8fd0dc9bfc2426229a7da934cec2"
     ], 
     "ci_platforms": [
@@ -24491,6 +25023,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1586adc8c21b5796ba52203379faeb5f251f5c1d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5"
     ], 
     "ci_platforms": [
@@ -24508,6 +25057,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1608a688768bdecdb205a455401ce5d9a1424a22"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/162b4ec7cf39df091898e01057b2fa39605b34bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d"
     ], 
     "ci_platforms": [
@@ -24542,6 +25125,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/16858f1f9db0e248a15ce09d9848612de1f4bba6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/16a9beb811f836a444172a5da9290b47d77c32ef"
     ], 
     "ci_platforms": [
@@ -24576,6 +25176,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/16e681f1867a1ac5612e1a88fddaed0bcb4521e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/16ebac3f7cea2b46f660ec6a5ef3401c3e17a2e9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4"
     ], 
     "ci_platforms": [
@@ -24610,6 +25244,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17ec0503991dc248d2b188edfa3d28573a1c2154"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17fb35db0b73c331a66120dbc491300b2d1665e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/183c878064b6a0ddf6a22dc4a2aa0d33a2d802d0"
     ], 
     "ci_platforms": [
@@ -24678,6 +25346,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/190c4ca0cf29c99bc987d2792c7f62e1007c0245"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1949f4a75f7d501d5279a01f58a444640379bd78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1972f535ae202777efdd15a09138efc37e07ac01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/198e691a9dabd23ed5c156f3a6e2c06a4379c15b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/19dcc3082c76b85177ce6a56d195473aaa285268"
     ], 
     "ci_platforms": [
@@ -24695,6 +25431,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1a16a4b32cb0cb3a759ec20edf332cdfc5d1717e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1a6b907bfa02ceebeb80aab47b3c3c51161eb868"
     ], 
     "ci_platforms": [
@@ -24712,6 +25465,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1af0744fe0ccad11d6df023803ab699e1464c8da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873"
     ], 
     "ci_platforms": [
@@ -24729,6 +25499,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b6d8326532cea974655dc86657d8e3b9ba021de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b78d906803b539ea9f135e41b58257365948855"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1ba0190ef2cde93332f850753a05b89ae5f39f1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1c0417c96e6408d2902ef8fe4b8cd05f1ce4a50f"
     ], 
     "ci_platforms": [
@@ -24746,6 +25567,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c24396c21f2c6aa2ad9b9a14877b7edf0ce61d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1c6e5ad8dbff133707cc85b05a0057abf55d08ad"
     ], 
     "ci_platforms": [
@@ -24780,6 +25618,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c86c4f2d173059e5cfe67b446fdfa285743f61f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d"
     ], 
     "ci_platforms": [
@@ -24797,6 +25652,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1cbbae18babaa20229b42b4633ef812bd3b40ad4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1ccd81836f26b7ececde2b02a22b19ab2a498631"
     ], 
     "ci_platforms": [
@@ -24814,6 +25686,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d55650c5bc30ea68168a9287820e25d2d53ab4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d795268725d3a08883b05b021a437654aaed908"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d7bd5961f6963c65054fb9a24d913601f37bf3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1d8b40b4798e652184df3bcffe1b1d7e32648f79"
     ], 
     "ci_platforms": [
@@ -24882,6 +25822,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1eefda69c1787cc55a8bd43774ca13563e0972bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1f4d0adab39a988792cca201626c28293e247226"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1f7847ed44c5acbc52c5d16b0222b44067076478"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124"
     ], 
     "ci_platforms": [
@@ -24899,6 +25890,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/200521ca3891bfed841ca8c22691196a1a03ccd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d"
     ], 
     "ci_platforms": [
@@ -24916,6 +25924,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/205dd562c7202d4231b232a6804889e77eba5292"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/207c5a0f80f052ac7b48f6dd45cd33987be27f32"
     ], 
     "ci_platforms": [
@@ -24950,6 +25975,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2193a1e20caee37676d08c88154a462acf120fb0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/21da45db854aeae9bef8576d6cb5859c0cf7a34c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/21f3be485826850e4f4670bb81982e2827815426"
     ], 
     "ci_platforms": [
@@ -24967,6 +26026,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/226b0315f87b08521c9a2d3e2b50c01ec421be14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/22c9ed2979d9963bce6500997f1e0433988e7e37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398"
     ], 
     "ci_platforms": [
@@ -24984,6 +26077,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/247d0d09deeeb76422cd1d06305a63378a498656"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/24a87af0954c808fbd3f2c55185d4b1fa9459f4e"
     ], 
     "ci_platforms": [
@@ -25018,6 +26128,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/24fbdfa73f26686633871ddad9698d7059db488f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2500fc12d5d1b5ed99fc3fe518c28849d1c8d6e8"
     ], 
     "ci_platforms": [
@@ -25069,6 +26196,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2535940afe69b3106b7696a486a2617d0d9a7150"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/253b8946a7cf403dd466f1685df2f741d4660a34"
     ], 
     "ci_platforms": [
@@ -25086,6 +26230,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/25aa74daea95f9fc46a78239bd2e78ccf0fb3ffc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb"
     ], 
     "ci_platforms": [
@@ -25103,6 +26264,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/26930c35fbe83e4d165b8b7f218ac8ea231c87dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/26dfa46c2bb2e6af6f52bac6f03a9e4406c6e700"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998"
     ], 
     "ci_platforms": [
@@ -25137,6 +26332,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/27a8643ba6047e12de1b2a4f7d0994a2c095a6d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/27f5e317e8a3a1098e786b96175c15d0855c4855"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972"
     ], 
     "ci_platforms": [
@@ -25154,6 +26383,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/285b0b9b11fe506527c880d3a866ba94f8038cdf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/28851da472cd09123465241e0d59697f563f53a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/28c56acb0f9b47ead49f34c0d92a661fa04952c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/28f8c7af6aab3bbabe028f780e174b27b924a146"
     ], 
     "ci_platforms": [
@@ -25171,6 +26451,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2923d9c864597016358f37ce4014c61648b7290a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2942908b7973da7113098a0ea25487e3372db173"
     ], 
     "ci_platforms": [
@@ -25205,6 +26502,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/29a6d7ab3e7ea8d331358df45e5b0926e768e227"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a410e3d783bc93e63206e28f92b6a40e1db09cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766"
     ], 
     "ci_platforms": [
@@ -25307,6 +26638,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2b80854b52267dd70b622670e401280387f15dd2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2b931953e9bd02c3310a05234e91550bcd8ddf62"
     ], 
     "ci_platforms": [
@@ -25392,6 +26740,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2d61ec2cff75eadbc47e0932998b8a797e0cd96c"
     ], 
     "ci_platforms": [
@@ -25409,6 +26774,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d7f42d3df4a206d09a9fa3126333a61f5e678ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d82b2376d689485814ade91df8f65ee08395a02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2d9440daa210b9298f34982dcf7adc3564ad965c"
     ], 
     "ci_platforms": [
@@ -25460,6 +26859,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2df65610f1c24ad1cf9a5b22614434c96ffc12fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57"
     ], 
     "ci_platforms": [
@@ -25477,6 +26893,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2e48a9c8d204975060e81f37c7a46ab501750067"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2e7441eacf8fcc7043f24b3beba4fcbe3c0c5ea0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2e82bfb7e8eede401ce75f6afe8c15ffd06130db"
     ], 
     "ci_platforms": [
@@ -25494,6 +26944,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ef149e8fd68e06fcb7ba2fb43a17cc1dcfd989b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2f0a8f0f96402ba1681ab3a9095a3dea47cdc53f"
     ], 
     "ci_platforms": [
@@ -25528,6 +26995,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2f35914500b09477fe245bc130f86bbd15112ce7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2f44fd38efef5818750f9adc9b133e40f9cdec71"
     ], 
     "ci_platforms": [
@@ -25579,6 +27063,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2fece42b158854855dd42eac3fc7b8f1eb61fb04"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3017e9f66dacf5a01f8c7d65b8a72d4f68aa6a28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/301c057536319f49dcec68ab96677714e3dbf793"
     ], 
     "ci_platforms": [
@@ -25630,6 +27148,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30948ba77c2e56903a9ad5190cc74e59d42f67fe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/30fbe0ac4c74e2be3edd4f21b72bcae02e6c623f"
     ], 
     "ci_platforms": [
@@ -25647,6 +27199,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30fc581d975cd8384b86be0ae59792a605ca68c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/313001e1cc15ef9887b43e0c6de398eea2f20e00"
     ], 
     "ci_platforms": [
@@ -25681,6 +27250,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3152365a4d8540623c9fb3a93712d096bf6b34e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8"
     ], 
     "ci_platforms": [
@@ -25698,6 +27284,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/324b9341bfc56b24a60f0687a52981fcdeaa8733"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/32594aaa716c1a04b0f927ef964f1593735cb289"
     ], 
     "ci_platforms": [
@@ -25715,6 +27318,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/32a6ea045d1288418617e5e0c52ae02c1f6598aa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/32b9de8461fd32b1236abb86abc91c82652d6e2c"
     ], 
     "ci_platforms": [
@@ -25749,6 +27369,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3356fa1721a0dec9fedacba8d86e6100a49d5316"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41"
     ], 
     "ci_platforms": [
@@ -25766,6 +27403,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33af00c8deb0f0fdfc113f21c3cb5769aa474587"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33b7cb7d4dcd380b207f1137722fe394de2a0f8e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33ff864434b4f0c0e08c00ec2442cb521e9f79ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/342d148e59fb500ad76d583cf828c16cd3d3ed2e"
     ], 
     "ci_platforms": [
@@ -25800,6 +27488,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/34aca5e37920615e8c141ed1fe4e419ae2e4df65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/35ba1a4df4d362ea98e9386269bfbb95c5ed4874"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083"
     ], 
     "ci_platforms": [
@@ -25817,6 +27539,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3662f5312562bbe4503018a820692962e7dd66c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/368d2b5d4c6776afbed8e5e76cc3a4ccdde1df42"
     ], 
     "ci_platforms": [
@@ -25834,6 +27573,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/37309bbfb4f0d78e6138b13a4e5da5944c95b97d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/37bc0646132afe8c79cda5e76de150a473fc0680"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e"
     ], 
     "ci_platforms": [
@@ -25868,6 +27641,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/385626d51cd29e1b32befeaecde5df7248270754"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/38a55e83e685617cdf72e95f1303857b627ae346"
     ], 
     "ci_platforms": [
@@ -25902,6 +27692,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/391ef74273ae5e1cd8a2342c5370fde5df1a7140"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/39525bbff413519199d1cf2c564d62b9c3c7736e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/39b6daa9ae088667c5080709ca829cf51e66212d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3a287590e2d38d5dbc0b85d29ae2497d27aa0305"
     ], 
     "ci_platforms": [
@@ -25936,6 +27794,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3a90fbc998ad7219e447db6155e6174e0117dd49"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3aee5ced2869452b8ed65313d01b9b9c87144cd4"
     ], 
     "ci_platforms": [
@@ -25953,6 +27828,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3af9522626ddfeb1ef461e3ba0f397ea4b2d99fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3b002ab57ff8080fbb1e72d985ca6f59f96a171e"
     ], 
     "ci_platforms": [
@@ -25970,6 +27862,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3b60e6663ac7ceaa40f91d3a68fcb9c35e3e99b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3bdfaad171c20468a866329355621cd579eff21c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c18f7c2d8fef6f119fe5bdbb5d191a92c627cb3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3c84d21c46b89e7573750dd4517ea2eb58e37e27"
     ], 
     "ci_platforms": [
@@ -26004,6 +27947,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c933aea09501c81d7e065c671cdc3bd55f8caf9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3cac139b58decec7c0d1f1318e8f1f28f9650c19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3cd19f8138a81f242cb92212df2b4812cde8385a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3d7d13b272c46ccceca36729e9893e5142961fd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3d8c66be71e0ae0dfb0c2c7b84e4d8336f92b7ab"
     ], 
     "ci_platforms": [
@@ -26021,6 +28032,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3d9534f373e79edd704cc9529600efd62451fb78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959"
     ], 
     "ci_platforms": [
@@ -26055,6 +28083,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3e4c1755d1ad78103f10c2af7c7d2f86326f02f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3e8bef87bb89525914b5e7964969a66eabc78eee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c"
     ], 
     "ci_platforms": [
@@ -26089,6 +28151,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3fada97db682f675597cb58c5d43a72e283ab960"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/40b4b92460c4e76a39af9042fb3d86d491a98e16"
     ], 
     "ci_platforms": [
@@ -26106,6 +28185,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/40fb9f1d9086ace2de0ad59648d196ba0705ae00"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/41921ba00dfc038778074b1af81104555ca74927"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/41de80653b78b98f5caa7f6d00a96d72bc245068"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4212d95c0bfdf34b9c7fbd05bc732fa1bbb226ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732"
     ], 
     "ci_platforms": [
@@ -26123,6 +28270,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4236180c7d6f2edba5355b79bbe1a5c16266dd95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/428b5b04a92ad6c28fc38451236c85338b9f8ce0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97"
     ], 
     "ci_platforms": [
@@ -26140,6 +28321,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42a92ac224829067ee7dbadafb777bd38f076c6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42c2e90f2e228d6bec0d81e55f08647a2d651bbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/42c3c4a4e7d21e79d1e36494d5324f10a5ecbb04"
     ], 
     "ci_platforms": [
@@ -26157,6 +28372,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42c50f9543819ff7f440a7ac660cea374355c455"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42c5f1965243b4bdf0212123d3430010bdacefaa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4305b19e8a214d2cf47436d964d52d10e430575f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43646936116c18140ff0f01306d16280943eedac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/43676969fb81dcc1699b6a17eb465ef3cd4c2ab8"
     ], 
     "ci_platforms": [
@@ -26174,6 +28457,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43874e2bb721b485a93d80b7f1c3e3630f746b02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/439d4e4ed3ab9fe77e2bbda5b2be3d123beefa00"
     ], 
     "ci_platforms": [
@@ -26191,6 +28491,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43ed8f46ad700ddd4c2a7a15f0cd209954f0a774"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43f79e748c5da73a13555b00cf5050af68f07829"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43ff758aba2eca1e355f0062ca8fa2dcc8edc69c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/441c94c010d19206c337d3c850cc449523ab480d"
     ], 
     "ci_platforms": [
@@ -26208,6 +28559,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4427b547b6693c39f08ba67c5d2ad012d5088f83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/442bb0df4955b8dc95cc69af79a522a04c23dfe1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/44378830a865936e205bb757a69bdf8d788bf26e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4449ec3eda232c394fad83e34b002e9bb46862e1"
     ], 
     "ci_platforms": [
@@ -26225,6 +28627,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4471ee009359844e7600175546a3b36a21329666"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64"
     ], 
     "ci_platforms": [
@@ -26276,6 +28695,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/454fb5eab23aacdba559ed9a9a36941732eb3276"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/45657516294c5426c490e6aa522a79077c972856"
     ], 
     "ci_platforms": [
@@ -26293,6 +28729,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/461949a48f4f2234cce6bfc1476bc9fd96552c0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/462ae7e1d7eb4a4d8b4d5daaa1422b7cf835e127"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/46325fcd7a3a718f2188f49e28ad9d0c9dcd06a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/465b299ab3509b61016406e0d1d93f7774c03c8c"
     ], 
     "ci_platforms": [
@@ -26310,6 +28797,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4667156173c437c62fdea99a199f3aed0b504fe0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77"
     ], 
     "ci_platforms": [
@@ -26327,6 +28831,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/46f88af92fbd99c386bd24d8a045a9a9c2469d53"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431"
     ], 
     "ci_platforms": [
@@ -26344,6 +28865,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4799a2aacdba08bd3e418c5659060829a997d715"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/47e402f3386843e0055431750f30b710e10295dd"
     ], 
     "ci_platforms": [
@@ -26378,6 +28916,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/47f2ead1b9cd99a8603dc5fd583afe3d4287deab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450"
     ], 
     "ci_platforms": [
@@ -26395,6 +28950,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/485410954a625f5749bce6ae923a620371542ed8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/48f56289592da153b3c50bcc26ad6d4d3a7e443b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4905b3fb0f7d2196a5612e8e432abda666e4317d"
     ], 
     "ci_platforms": [
@@ -26429,6 +29018,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/49d816ae44b329820f47979c5790eebc8eadafd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a2ee017facf4df1929e7db4b34b12018b64461c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4a3eae69f4c5dc768b166620af348316c9fac3e6"
     ], 
     "ci_platforms": [
@@ -26446,6 +29069,108 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a97016bb83b0db1c51fbb4d4f9c909dd85bdb41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4b011706723e645407b871241c2c11004103d628"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4bedfc6d01a2d6bc0911d48123d6b8b30a46732e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4c03f9d60bfc5a2ab41c1703672a339838890ef3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4c34bbb26218f40a8ea1bafc8c50cd814a781cd2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4c3dcb9cb14f89b3616fc7cca78f2ebc502907eb"
     ], 
     "ci_platforms": [
@@ -26463,6 +29188,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4c6258b5299bd03560e292fcf3008efc60bc6cd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4c686a41d4d2226b3cc76b8154d8df090d075f00"
     ], 
     "ci_platforms": [
@@ -26514,6 +29256,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d7b5b98536de248387605efd813ba23b8b613dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d800cf62e39478c1bc1db8222a8d810fff6ad85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d81efc0d5945caada326e2f6e55167120f0d3ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4e36813fde9b5de1b62de95f498f2e0a48b5c5f7"
     ], 
     "ci_platforms": [
@@ -26531,6 +29324,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4ea18756816848daf5e799ce1d75ecf52353eb08"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83"
     ], 
     "ci_platforms": [
@@ -26548,6 +29358,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4f320381bfd3927493db8037238bdce1766c68ee"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4f53cc7b3ed0c77c3b5e4478f54caa40e0bf64b6"
     ], 
     "ci_platforms": [
@@ -26599,6 +29426,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/50a96367b6a52c58a36364f4b1ec0583c7f315a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/50bfe6100bf11339372ba29fe0c9b38c3ec2ebf0"
     ], 
     "ci_platforms": [
@@ -26616,6 +29460,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5151ad7147bbb75b1b377ce03f4ef5ef0f4f1c82"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05"
     ], 
     "ci_platforms": [
@@ -26650,6 +29511,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5220909c423d2b321e8459355c965fb330288565"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/528cc09294d2288fc91a4bab7cf6ec621c6621b0"
     ], 
     "ci_platforms": [
@@ -26684,6 +29562,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/52b5c86f262d46624b2211151a38cbd69c705734"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/52dba1b997f903c5fa3d7da71421b36d96d9f55c"
     ], 
     "ci_platforms": [
@@ -26701,6 +29596,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5394ae134e9023432ac137789815e2b24d1bab3b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/53e68cd362f3c8d64941efbb0b527c52da5e8424"
     ], 
     "ci_platforms": [
@@ -26718,6 +29630,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/53e9f9a4b0347651b3833c3e153e743a1194e0fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/543ea879faab347874ad5e297684a62a1555e1ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/546fe2e2b1e2756c3f121d0545866798c85c9b8b"
     ], 
     "ci_platforms": [
@@ -26735,6 +29681,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/548190b9eb539e0841bcdd6e2c095cbef6ebd119"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/54a0a2c37ce1830f241f6e2828adc8057cfa385f"
     ], 
     "ci_platforms": [
@@ -26752,6 +29715,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/54d5ac6cc4bd944e60b7464e36c5d1b144c17da4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5515fa05b890973031b0e2cc8c2925f3974e2821"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f"
     ], 
     "ci_platforms": [
@@ -26769,6 +29766,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/560fe3fe0bb266ccb8c59ce19302bce23835097d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8"
     ], 
     "ci_platforms": [
@@ -26786,6 +29800,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/56ac47e07bf3f42310773a4c66ee9d3afc27a8a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf"
     ], 
     "ci_platforms": [
@@ -26803,6 +29834,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/570215c70de40add2ad62bed9ce47f8b6b231de6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/572ab3983e406a82325f02edfdd7981d040cfbdb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/573665d817a96a324fb8ba40a06425f572327b78"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/57798cc4375de344391221fd07d591f5c64d646d"
     ], 
     "ci_platforms": [
@@ -26820,6 +29902,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57bc1a4501ceb31b4ead1c2428798be073eb9db3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739"
     ], 
     "ci_platforms": [
@@ -26871,6 +29970,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/58c57e0ef4c2a630150f53ccdc2bfa798d5b9eae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5939ec5fd8f4e02ff0720cfa3ef685876bb3549d"
     ], 
     "ci_platforms": [
@@ -26922,6 +30038,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/59de0a42d012ca3dd8b7fa2f1b1c6642cb86fad4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a1d370abacb9f46fa966c8e58992897606a7900"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a34e7fd2ff3f8e32ce85138931a387dc5f15db0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5a3c9d98651a315b5bde737482ff54f6b90361e0"
     ], 
     "ci_platforms": [
@@ -26939,6 +30106,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5a3d25f74f7629c675be11faaea35921229b8757"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5a6491ab9c23fae58967d4a4b5d5cfb23f620001"
     ], 
     "ci_platforms": [
@@ -26990,6 +30174,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ae4d5439ec6910a5fcd9c41f20ae843942853c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5b3f6f20f348cc4e5fb07cdb6e8614ca24f2cf13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c"
     ], 
     "ci_platforms": [
@@ -27007,6 +30225,108 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5c117dbd5d3146fd94c667f15f4c006fea88d14d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5c388b60e622e14c9abfb5b46c65207a319e09e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5c43f3a5de9c581693432dbb2ad604550c3948f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5cce719931cf1f07536401134de4325b942be87d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5cd55495dee689728feee959bcb09e2ab13d013d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5cf8b4c70476c124711e731cd2e00f67906bd457"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690"
     ], 
     "ci_platforms": [
@@ -27041,6 +30361,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5d5ce71ab1258e014e06e6a2edb94a47a4ae1b35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5d765c856a9a8650e1b17813340b9b6ba0989b58"
     ], 
     "ci_platforms": [
@@ -27058,6 +30395,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5d76fdb98fb38243a1f1c5f96d31ece34c5a91b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5da437d4fd58607deeed34bcb21accece71a056b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ddcbde7afa43e7fe4e44ef1470fc0c282873cae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a"
     ], 
     "ci_platforms": [
@@ -27075,6 +30463,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5e880db498f9baae544cdbc23476873d8766ac58"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5ea01efbec747fc55ae29eb2b779f00889ca6922"
     ], 
     "ci_platforms": [
@@ -27092,6 +30497,125 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5eae70ef8ab19fead6a9275e3e40df6b201159b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ed431181bedd9a496aa3bb2330957c621f1443d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ed8998cfc22cce008e3988b3591b1c9ddbfaa75"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5f07e5246d765494ee26c689072ab3ced452f30e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5f7eee027cbd6ae8e989150d9bd8a4fd39654c01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/600096fe00d5f67726674fb9b0d2a6621a25e79c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579"
     ], 
     "ci_platforms": [
@@ -27109,6 +30633,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6123f6116f3cacb4aabdbe26aed24ed0981d6c1c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/617a2a3f6b6d5d53993db606a8818235ae8d9b96"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/617ef08330c0e852f9aae6c63ddc5893b8b2c722"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6184ea16753b0827f728285f18dad4b3bde00024"
     ], 
     "ci_platforms": [
@@ -27143,6 +30718,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/618e64836dc7f374745be963b7b3c62cc02ae2ca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/61ce843c87f7bda1fabcb6ae3f41e85e6e2332ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18"
     ], 
     "ci_platforms": [
@@ -27160,6 +30786,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e"
     ], 
     "ci_platforms": [
@@ -27177,6 +30837,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae"
     ], 
     "ci_platforms": [
@@ -27194,6 +30871,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3"
     ], 
     "ci_platforms": [
@@ -27211,6 +30922,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2"
     ], 
     "ci_platforms": [
@@ -27228,6 +30956,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b"
     ], 
     "ci_platforms": [
@@ -27245,6 +30990,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156"
     ], 
     "ci_platforms": [
@@ -27262,6 +31024,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653"
     ], 
     "ci_platforms": [
@@ -27279,6 +31058,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/660c071578cbdccb503317ecbf2fd331bc4ac82d"
     ], 
     "ci_platforms": [
@@ -27296,6 +31092,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6639deedbf04eceba6017f712b287235540b5528"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/665d7b4f8082be87864e6ad3a6a3faa1d52ad6e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/66ac31199d08e7a3b066059cd409457a850847b2"
     ], 
     "ci_platforms": [
@@ -27330,6 +31160,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/66f0ed73b2d4ca3edbd23d5b669e75e4d0ffd292"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6722929b4924f4d50ccfb999460e9a31ca104b4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f"
     ], 
     "ci_platforms": [
@@ -27347,6 +31211,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6868e669f4b9a77ae5227767ec455fe6f82e55a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6887af467b343d6e1a8125ef10eb0a630f2dc06d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/68c65dc60f887050eb8cd7f946bf37aea2ade9f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/68f9d39b83bbc7cb4f743c8814800e6692988897"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6914f5f380c83ff9e3e90fc60d5048e47e5e77d9"
     ], 
     "ci_platforms": [
@@ -27381,6 +31313,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/69d0f8b4a9452d11620c7d3c1fa532a618d65858"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6a10118289fe7179c4e9bb6a1b466ba34c582bfb"
     ], 
     "ci_platforms": [
@@ -27398,6 +31347,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6a1d877fe1eed1199511b8f28889d8f17665708e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ac88da4119df5e1592a05bac7ecb92af59dc1d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6b1e10a936df3b42720ebc9179fb74aa147f8b14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6bd27df0dc9a3f73108de7bad443433aa5ee1175"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536"
     ], 
     "ci_platforms": [
@@ -27432,6 +31449,91 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6c5707e8b1aa9a70ec87014cd660df4a7b910ee3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6c91623f5a30f65110a4083897bad2882f032c51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6c9b144f4e6dae6944b524a077dde07ac79e58d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ca83e5d3f4544a14da513dc798f02464febdcd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ce9895c780428861d12440946508c6641352544"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba"
     ], 
     "ci_platforms": [
@@ -27449,6 +31551,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6df1c575d7f8fdf5593f1f60d9dc540d018fc58c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6e1cf196e7c8ad4226d89f3ca2c6f7949598bec2"
     ], 
     "ci_platforms": [
@@ -27466,6 +31585,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6e97f4e782ca976d4890199d48fcfd64173e24f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f"
     ], 
     "ci_platforms": [
@@ -27483,6 +31619,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6f0bbfce7c5027932fb0f809494413e12a4ad3c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6f39da8f5bbae89a13dd36755f7b3c4a30c25833"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf"
     ], 
     "ci_platforms": [
@@ -27517,6 +31687,125 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6fa93aadbb6ecdc32c9111be7692ec28ec11be72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6fb7b01c1b363390eb9188bcac05f8f11e20c01d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6fbbaf9f6f49fabad4a0e47cea9e4048d8f130ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6fe041f1468b495d3186da906f9a5091e5761387"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6fff95a8d3566b2721fa46e9828b47635f13d9ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/700f56e26286daf472d371effb9bca13fffa3d77"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/705c87b99197c87eb2ed148f8b3fdc60f8616f15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/70bd921a3d4700d49ad6b99e0cfee42c36a13b3a"
     ], 
     "ci_platforms": [
@@ -27551,6 +31840,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/718d23058d5c805a2984c087cd89f9cb6af065b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2"
     ], 
     "ci_platforms": [
@@ -27585,6 +31891,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7217d93c1da3ae8ed085a5e6988227dcf430cd89"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/724063b7a5ee36246d72923e776331487434b81a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7240f3408714c2dcdcb448f234efef4f08e6b2fb"
     ], 
     "ci_platforms": [
@@ -27636,6 +31976,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72a79517b8f9b57f62dc1203a6b5eefadf27c088"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/72c363848fe754c23e1f9f2acc2f025666417d2d"
     ], 
     "ci_platforms": [
@@ -27653,6 +32010,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72f71befa8ebb4b2c1842aec78d840b2a4abdb85"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/73889340124f1f88859aab4e6ce36c0019a44218"
     ], 
     "ci_platforms": [
@@ -27670,6 +32044,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/73a6e07089ee011746c1ec3146b8a1b4b82c835e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7421d8acd877abd9d437ad447dfae29893cd2f37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7462e4d1834938e8a5fb975da6865cc7d6b225f3"
     ], 
     "ci_platforms": [
@@ -27687,6 +32095,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/746d9837f0fc3c989b7fe0585b8365478f1c21fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/746ecd23f1c41206dd4180a7afb032411f315d73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7487f56a435277d9bd7ef38d361e8ad7cdf62375"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/74b69a49c2df95009ff18d820bbe7fe6ae797aae"
     ], 
     "ci_platforms": [
@@ -27738,6 +32197,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/75755ae5cb0ae4f711dd15925f9f681d23408bb8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/758ce3af56f75edb8faa20ef78ffda5511dffb3a"
     ], 
     "ci_platforms": [
@@ -27840,6 +32316,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/774a64c60765d78b3b980ff9a6538219d6908a3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/77d4480781e1e1a9d5d5c02ff53fba10127f8b6a"
     ], 
     "ci_platforms": [
@@ -27874,6 +32367,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/783b1f17ae90eba0ff7728e767b56ea6885e0b28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/78499fa2980dce2fde92b74421f486bf544cfb8f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/788f18727a0aeb5e200527bca7c889c9954be343"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/78c3bbeaeb266aac1df0d4abe78bbca68fb085a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e"
     ], 
     "ci_platforms": [
@@ -27891,6 +32452,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7957953ca449974ec39c6a137c0acdedb71c3b02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/798fd96821ee3d91952373024f35cdceb10ccbed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/79ac297c667d2ae77c05d2af275b05138439ee5b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7a0b2f8659484409af6a76d1df273b8dc66e3439"
     ], 
     "ci_platforms": [
@@ -27925,6 +32537,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7b4b493ac5a36d3b3fed0b66bc504206548a3537"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7bb25e1821f1ff6ea4c85259444f7f40b430aa1f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7bd75ddceb75724e5e9205cf7fadec03d8e1aca2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7bdc25dc79ca942673e515126e22474fd89ce55e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7be89fb64b3d931387e8a5b1ef51bf9cda18006a"
     ], 
     "ci_platforms": [
@@ -27942,6 +32622,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7bf8d2b77d85e4042e47d0dbe6da9441c6d9530b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7c026422a34cb34de673a1d6702cbde67d112d27"
     ], 
     "ci_platforms": [
@@ -27959,6 +32656,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c193442a422da21cdeb14f681b0d4179aaeaf5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7c58daa09675ba2b11e69636bb78dc0d1343bb51"
     ], 
     "ci_platforms": [
@@ -27976,6 +32690,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c6a381eac8fbc8fccada2b2069c3f773a9c6961"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7c70dd584df7a4fda61d08ab8ef85ec70c85b7f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7c9b4e2ea03542254235893edd042a822145e504"
     ], 
     "ci_platforms": [
@@ -27993,6 +32741,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7cc958be492e942df2b784fcc08a63d57c7fef92"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7cdff0948ef64e551ad02f857acd5956d91530c9"
     ], 
     "ci_platforms": [
@@ -28061,6 +32826,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7d8eeb8778051e621abf74daf43dd4010117d9f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7de73ddcb20d0940b937323599a5094bfb26ae6c"
     ], 
     "ci_platforms": [
@@ -28078,6 +32860,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7e29172a1d27c4f8a0b138306db1043373b2d0ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f"
     ], 
     "ci_platforms": [
@@ -28095,6 +32894,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7ec62c16916c2c30847b578d2148893924287bfe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7eea6a4b31c4f10281f31a7461f35af7331becf2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7efac665d3dabc2162f4407e3bedbd65b3007335"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7fe7a6ab57422c40c7e0e2333c3bbb6ae6a0d9a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544"
     ], 
     "ci_platforms": [
@@ -28146,6 +33013,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/80ecd5087801e974eae7db730a496d2aca110648"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/811533455c494627bb5b5802f4ed7a386f57cb1e"
     ], 
     "ci_platforms": [
@@ -28180,6 +33064,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/81489a0c6a71c48e9f343cb5ff8e8b5693d5df19"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/819cac3befd0d7b12ffd734c26df1cdf43c376a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/81e64ec00272538edef6336423738277647b5ed0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/820d5ba2e9d91563dae39a1b02833fbef1e6d8f1"
     ], 
     "ci_platforms": [
@@ -28197,6 +33132,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/82182d7a9c73a70f5eec58c03b1db511d7feb95d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/83c29132911949c65d508753420708e9a0ffd6ab"
     ], 
     "ci_platforms": [
@@ -28214,6 +33183,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/840928fe62714fdb003b3f0a40c2c4897f9d7938"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/84650393df0dca7ca3244faa7ac036873d3dcce1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8492f54a92f9a2a05af1a078489a3a68145d8985"
     ], 
     "ci_platforms": [
@@ -28299,6 +33302,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/85bd45792a3cf2116fab5e99e2d824ee804af843"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394"
     ], 
     "ci_platforms": [
@@ -28333,6 +33353,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/875280c0c54d1662b07150e728f9ac0c1af7bf66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8778868ac7a23d552d93772aa8566cf427a0c1f1"
     ], 
     "ci_platforms": [
@@ -28384,6 +33421,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/87e510c4dd906ec4de0066e93b2475480fc0768b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/880070b48f04fd1c8ffafd750e1c4d37ff404c6c"
     ], 
     "ci_platforms": [
@@ -28401,6 +33455,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/88139a0d01f144556ef861af4450f466081443f5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/885267691bb42bc807b6e578571430a81513eee0"
     ], 
     "ci_platforms": [
@@ -28418,6 +33489,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8854a331f3c5ddc4ace70e0505901e53aa48e386"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/88600f27cb602db290f07eb0e8b6f10488c0760f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/88be31c841a66f523045f7bd1708ce64272e4276"
     ], 
     "ci_platforms": [
@@ -28469,6 +33574,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8979c4017b72b970dc33095be26788f52f37a959"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8a034b07b9baf1b441c0fb0322652772973f20ff"
     ], 
     "ci_platforms": [
@@ -28486,6 +33608,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0"
     ], 
     "ci_platforms": [
@@ -28520,6 +33659,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8aaa277cf855a972c6dec9fc49b171ce3232a26a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ab19633328ea9e493dee313e135e7d851aa7911"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8b253ba946d6768c147f5d52552e150b703437e0"
     ], 
     "ci_platforms": [
@@ -28537,6 +33710,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b30c1f058ac421b6c51c4591ef9e4adc2886b44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b37ce939cb8d42c459f5e286de980c7b62f14be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44"
     ], 
     "ci_platforms": [
@@ -28571,6 +33778,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ba87aeecf944e0eb387f8f2d9e30964c9f860de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8bd94413e2d60effc2806dd7153216a1b6487162"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8c501e1c87c42c4b7765ab027bd537ef72656605"
     ], 
     "ci_platforms": [
@@ -28588,6 +33846,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c540353717db453eeb865e5b9b7f2efe6c5d5b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8c5bbcc6935d43c94a0c4ce4a5da01c04fd223d8"
     ], 
     "ci_platforms": [
@@ -28605,6 +33880,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8d386a409662ef68370c0c552742bd0ea6d527d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99"
     ], 
     "ci_platforms": [
@@ -28622,6 +33914,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8d91dd322c7972a13cb98461b0eb284116905887"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8d951b7ab0231fb1dc573433b354eac58c699c36"
     ], 
     "ci_platforms": [
@@ -28639,6 +33948,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8dab1d2d4f470c669688103f52718a7783113cf1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8dcb4dd3d2fa04ffc83f7fd7f9306ae4105ef7ef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc"
     ], 
     "ci_platforms": [
@@ -28673,6 +34016,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ebddbd256887fb5fe1be69a46023b34f815d2e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8edad87970b31dad2b23184d864fe5ad9efb05e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f4187ea7f2efbcd933fdb2b0652b71ecaff7822"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8f43b11f10961dcce8eaa8340c96d10bdbc937ad"
     ], 
     "ci_platforms": [
@@ -28758,6 +34152,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7"
     ], 
     "ci_platforms": [
@@ -28826,6 +34237,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92ec3b6722dde442121b3d1ed3ef23976c72cba8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5"
     ], 
     "ci_platforms": [
@@ -28843,6 +34288,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/940a622e8995529f6b0455906d8a035902682d2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/940e35bed3ff2b52a29e5b15acf9fe39772eb5de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/94571a4b13c435117ef9bd914443ce9a07da8e3f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c"
     ], 
     "ci_platforms": [
@@ -28877,6 +34373,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/95940316e7104e9c2d5123b31e36b2dfd12fcea2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/95dd85860bde08e1d0ecef805ad55f66008923af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/95f223f8964d294aafc2a6041a83cfa7761c31ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9629c00d91e6146b29f7559a944e6bf8dce7d0f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9629c9a0c98f15eec2b7fd114fa5ff9ff5c61a19"
     ], 
     "ci_platforms": [
@@ -28894,6 +34458,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/96a6293d4fc97c75f037bdb0f73dc5b62bbfa2e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/96a80511d8ef3ffdd370a3cc9467713a538259bb"
     ], 
     "ci_platforms": [
@@ -28911,6 +34492,108 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97011f865fcf9c57560d5ed3cb05883ff298ee35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97440beca022cd5799f76654d8bec51f62c0bbaf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/976613cb09127a752d628c4a3cf73b8e3168e0af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97817475213736527fdc3b2a28cd45f52fe4ce1a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97efcb1f37032ebf01b4b1065a9df66590b7051f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/980f0198dc66e867b1a5d04cf24bc02fbdf3b839"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89"
     ], 
     "ci_platforms": [
@@ -28928,6 +34611,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/98569dc166bfcfef45a66db4de1c0f34340c269c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/988bd333d5dabe1561cf4429e7481ff110be0da4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d"
     ], 
     "ci_platforms": [
@@ -28945,6 +34662,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/98cdb5ba5725c6b2ed39fc514401fe987fc2d9af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9989534524a212092e9d7fede16106b586c434f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/999737edf1e9740df084c4326ec983137ccd7111"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/99e8f2ea80ed1d5a78fd5236e89d404bb0c03940"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9a0de0d63d44e00fc88e6cb88f4b8665db3b4b5e"
     ], 
     "ci_platforms": [
@@ -28962,6 +34747,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9a0f0818ff9fbfd81e0d0eadeef7b85ca2d4fd46"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9a24710002a240ad32b7adb5310f4970c09cc8ca"
     ], 
     "ci_platforms": [
@@ -28996,6 +34798,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9a9af9f266737f95cfedbf5c8fcea22660c3f085"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9ab3be55bd49749439f7aa1bfe2d178ad663b003"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9addda4c7a9940fbbda2218ec58560c10e1df9f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9b5b436057dfcf4299e52ad49c74e45ef04be7a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9b6f00dd2752afbd223aad960168e4e535330d30"
     ], 
     "ci_platforms": [
@@ -29098,6 +34968,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9cb91ce75745cc30995b8985a35ea31db766e54c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d004fd9a35647ba7ec169e6fedbf9dce5f9623f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d69b6fb15c861c294878da8aaf16a531dfb1b70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d74922516d210da71d40395f17a3cef4161894d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9d91fac343dd8a7848746ca5472fb1452052bfb7"
     ], 
     "ci_platforms": [
@@ -29115,6 +35053,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9dd25a6857d92ef52169ec95a0cdfbc8570b6d99"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9ebd34b96faba2fea70a50533df78a8c1dc35247"
     ], 
     "ci_platforms": [
@@ -29132,6 +35104,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f00c8665f3918e666d424ee67a2556f2651d64f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92"
     ], 
     "ci_platforms": [
@@ -29149,6 +35138,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f43969c0777a021539b59eafdac9dd2f51422d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f643e51d8e91e7e0348017d98078f078a1790b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9f77859f13bbe482011164f7a5e1a2a77d8596f2"
     ], 
     "ci_platforms": [
@@ -29166,6 +35189,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f86fc902ca36482d09f6c11e821b79bfc0b98cc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9fb07d3aba4e2d39eff7d31111515d7df2c981ab"
     ], 
     "ci_platforms": [
@@ -29200,6 +35240,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a0e80579e201495c2337292a3508b2d220e9737a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a10775155c8eb3a834d067c0978753513d5e1d75"
     ], 
     "ci_platforms": [
@@ -29217,6 +35274,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a18ed3861270cd42a661211d9d970c488fed46ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0"
     ], 
     "ci_platforms": [
@@ -29268,6 +35342,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1f6961a480f1eb49b394118b05b9cdabfb6f0a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445"
     ], 
     "ci_platforms": [
@@ -29319,6 +35410,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a36a156c5ed8a55aec450393deaed66c0e9117c9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a380f7e56171dc69269afb6364216bc69925eb8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3926a25374714a71c8bd515564d294df229c7cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a3c9b6e89b534d02bdad07207c4fdcda536f28a4"
     ], 
     "ci_platforms": [
@@ -29353,6 +35495,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3d52dfd05da328d3f109d125e6c1a15470eab06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a41e8b175a837b55e540874c3f056a9d9535866c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a4d41bf7bce38a255a431912f6b57637645221e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a55fb292d4e1ffcdaf933f2dbdd8410628eb7acc"
     ], 
     "ci_platforms": [
@@ -29370,6 +35563,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a619bb6ff4871fab3045e46bef8036f80d605f37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a62960425c597cf5d2bd38e9412363991479837f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a64136997cd4c4be7d93f10fd6a1d12cdc22691c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a6541e0f317553947d53cfb9318367aff2898ad5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a6914c7bbe81fd2138bc20e63b27c0cadd0471ee"
     ], 
     "ci_platforms": [
@@ -29438,6 +35699,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a8115b0be87517139447c9fefc33e225f2efdf32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a"
     ], 
     "ci_platforms": [
@@ -29540,6 +35818,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08"
     ], 
     "ci_platforms": [
@@ -29676,6 +35971,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abaca8e8237d5add7e35752471688233d265efc2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abbd9f85ad500d55dda6009681ddffca1849b632"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abcfa029d3eb7c016a162e78e7351f64b9905a42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abdb7891569085e3df0f6c7a5348c12bf3dd1ae0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/abe27eee1a472ac0dafe73619602ff44bf7d0657"
     ], 
     "ci_platforms": [
@@ -29710,6 +36073,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ad6369d2c51c4787778ff9dbd86cc6df44312f1d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ad8f14d76933f67a10d9e8442eaa1b88b2395cd7"
     ], 
     "ci_platforms": [
@@ -29727,6 +36107,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ada998a4b5a9895f514ddbf8da775f5c59736021"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/af042d0ae8cd624acfa12788ffc0154e6f49394b"
     ], 
     "ci_platforms": [
@@ -29761,6 +36158,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/af1fbe820d92608782360791113393055c171da0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/af990e5c81c307c188a79f4cdfdae4e8e15dc4a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aff1fdfe79c104bce110cec92e1e021caf012fde"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b05cbc7820c94bb3ee46dd3869ea39923338b4ba"
     ], 
     "ci_platforms": [
@@ -29829,6 +36277,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b2432248370f7590e894c54f2dd13fe9df9fa53e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b262c677b8c46262f1fc4982f5abf4ef603abe1c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b29d3c87c76355ce07ea4d4c354bf9d40294abb3"
     ], 
     "ci_platforms": [
@@ -29846,6 +36328,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b2af0db70de3a6ddcb188d1f6f2a673133a8f9c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b2f450dc86671548200a1fe6ee0ee76171edc578"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b33f833f291ebba4d777c2bae51193553c27d138"
     ], 
     "ci_platforms": [
@@ -29863,6 +36379,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b35f51d95f597075bb93cd9d2135870fe0a73486"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b37ab56aacf7fea7dcade26810117c45e6041068"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b37f3e85a80b5dcde6b48b46f162418fd2ee83ec"
     ], 
     "ci_platforms": [
@@ -30033,6 +36583,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b5bec1a19e2ca2394f2c3235266c22a7167bfa5d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b5daec8e0821e8626c9b93ece56ccfef0511346b"
     ], 
     "ci_platforms": [
@@ -30050,6 +36617,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b5dfbf1965f794634249cc6be9d20d2a9fc6e332"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b61f6be57dd30d8c76aae7b966ffee26093f49ea"
     ], 
     "ci_platforms": [
@@ -30067,6 +36651,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b6694ec2d425e8ce6ad9ff712a999fabfa5ce113"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b6c47632d8d697f9f2923bde053f7a5571150705"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3"
     ], 
     "ci_platforms": [
@@ -30152,6 +36770,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b892c064b2703ac0dc31766946be487b197a541e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b8a74cc440fbfaa2a523f20ca964976bde128fd0"
     ], 
     "ci_platforms": [
@@ -30186,6 +36821,74 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8d0be707d9505c0e63253904979492c22cd9fdc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8e06536840e31a343b3a42b677d623bacfccd99"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8ea2247c5b1636148fa66fdce22ed1cc72b6bdd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b9318513eb6b1db553855cd062ebbd4d1db9b846"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b93e4c7538558dfe92d2925646029b5dafe653d0"
     ], 
     "ci_platforms": [
@@ -30220,6 +36923,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b95899d40afc4b3ff87af2285b61ba66939873fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b96fd7809c6f18c465e834a96dd60b43b32fac73"
     ], 
     "ci_platforms": [
@@ -30237,6 +36957,91 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b98ef7107754379c22a3ad59cffa3183e0804c0e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b9913b354096dbe1796814e2cea80addef6ee386"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ba3d174125e7378292fcbad9bfe8129dabf88b3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/baab31938837e1a3cb49ca12fb886fcbb7d48501"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bac43cd2ed1dbf3a89a0c66d8983b586066ef463"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bad.bin"
     ], 
     "ci_platforms": [
@@ -30254,6 +37059,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bb2affdc830241ebea35795fed3bc8d478330eec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bb349c691efa909b4c5412b9210e1acf4a4b7505"
     ], 
     "ci_platforms": [
@@ -30271,6 +37093,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bb54fde05891ecc235263ad087cfd9682a25f76d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bba4073cde10ba7abaac18d6303e310d02a47826"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176"
     ], 
     "ci_platforms": [
@@ -30305,6 +37161,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc2967ecf8402d442ef63ca451497431932a7e57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c"
     ], 
     "ci_platforms": [
@@ -30356,6 +37229,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc8dd89f31fa5e89cabace6d7701d2a218f97aed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bc96b9415e9bb48d27f37d91c51d10ec08139974"
     ], 
     "ci_platforms": [
@@ -30424,6 +37314,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd04c9dc7eaf030313d4c87f190a9d973b96ac2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bd1ed73f6cf97f980d23ff2e9f4f4e78b80bda57"
     ], 
     "ci_platforms": [
@@ -30475,6 +37382,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd585e031f586c4313c6b00e5f247f6b272ce902"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bd5c6df9c2cfaa96d768b1fe6e8fff57bf1d02c9"
     ], 
     "ci_platforms": [
@@ -30526,6 +37450,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bdab9cab03ad7aa611612e02775018112303d3cd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bde8a553b10a613c32f800429a07f0b5a2d37e53"
     ], 
     "ci_platforms": [
@@ -30560,6 +37501,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/be29c4d0b6568b06c69fc339ac29890baac569de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/be40890ee61e101a7429d53cd9ffd59ee600e0f6"
     ], 
     "ci_platforms": [
@@ -30577,6 +37535,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/be757e0ca581bb4ec14fbba6e87569f93f4c7750"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/be8114a7bd73ce15fe0495171234d0af526e41f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/becdf72b57104cede4a1fc7b7a4c97a3cbf3b7b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4"
     ], 
     "ci_platforms": [
@@ -30594,6 +37603,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/beff7e2d09ef0547a3b1a498311c665954d8baea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bf0d70e0d09e5c2ddd79b55dbabdd58b385307f2"
     ], 
     "ci_platforms": [
@@ -30611,6 +37637,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c004d2a6d36524db9e0c18c5df6170366dd2b6f1"
     ], 
     "ci_platforms": [
@@ -30628,6 +37671,91 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c061aa42448363b548d90cbf4a7660fb2b043518"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c0bb5f00fc14ea4f2000f75e6d1d94f23e6203f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c0e04f5709338a500b3be166714ed7b0013c17d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c11e6f232cfdc5fffffa2c79150b5647704912c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c16876cdc8ab36ef7083bf4579849ee94239af0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c17ca23726e7bca7b0d92398f827cfb25c7f0d40"
     ], 
     "ci_platforms": [
@@ -30662,6 +37790,91 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c1ac67facfa4ca5ad92c3eed576a59d41558480f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c1d33a370a8ec2c2ea380472cc49172c679fa5bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c1d84db44208d08a84084986094aeac3eebfe3b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c259fba0af17dd1636501feddd52e501b51c4137"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c29f63aa5c4462b359c9028b6e6031dc088d7d46"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c2d14ed959df62d2f6dbe46c71489bed68e3c0f0"
     ], 
     "ci_platforms": [
@@ -30679,6 +37892,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c2eb3287f8b83c9281826e3c773ca347056ee115"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c32029d5683ad5cfa1af3b534c53bc2f7f513f50"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c343ddb31042500e460861abc70e98ce3088ceed"
     ], 
     "ci_platforms": [
@@ -30696,6 +37943,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c370cb2ce56d1006fea0af1a823042927c0cfa07"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c3ade78c7fea61ed2e2cd843f9c551b107ae050f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c40e43a76f0c493414386dd90ab892042a6914d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9"
     ], 
     "ci_platforms": [
@@ -30730,6 +38028,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c4b438b82ac86439296c31dd7de86a753034c807"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c5154ce0384c3becaf12f83c51114bb3ccd0b673"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c53efcb830c4ae5cba7b3e0803635445e1469103"
     ], 
     "ci_platforms": [
@@ -30747,6 +38079,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c5446cba5971d6f44ee93097a21c1b8936f4020a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c56726277ddeb233e30b6223158042aafb944191"
     ], 
     "ci_platforms": [
@@ -30781,6 +38130,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c6733483e94f755f1cbf796f8aa3d10a2c371aa3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c69863dd21c782e609d6ecdb9150f887a0f39989"
     ], 
     "ci_platforms": [
@@ -30883,6 +38249,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c8f0972dabb904bc6d35ed576fc9a49eb2ed5273"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c918b9e3e9cdfdb21d94ef0fba85b25f3ed9d098"
     ], 
     "ci_platforms": [
@@ -30900,6 +38283,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c93f16b5b678d3019eb05bd0774598e7d34e9b3b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599"
     ], 
     "ci_platforms": [
@@ -30934,6 +38334,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c97c41c0c76a901f458bf9b4d785fb53fe8a2980"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c9bda5eb1a93526b4809d147647cc78452988e29"
     ], 
     "ci_platforms": [
@@ -30968,6 +38385,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ca418a61964cb360014b574fe29aa20b193df04f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a"
     ], 
     "ci_platforms": [
@@ -31002,6 +38436,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cb9a688f0dbc2015c77920f344e2d029c87384ff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cc34f9a0d85a22556faffadf90182f7c44bf168a"
     ], 
     "ci_platforms": [
@@ -31104,6 +38555,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd779b587b80719e2838853c2eac8d4595c0faa4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0"
     ], 
     "ci_platforms": [
@@ -31138,6 +38606,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cf26c6969c0f649a2ccd780edb8b3dc314ff7701"
     ], 
     "ci_platforms": [
@@ -31818,6 +39303,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d079f5c8a10611dc655cef33f73100f5f43787a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4"
     ], 
     "ci_platforms": [
@@ -31835,6 +39337,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d107d21374f4dba27f173d4edd5c8009e3b0f8c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d110d5d3a672bf483f230825e735d372b0b2c1a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e"
     ], 
     "ci_platforms": [
@@ -31852,6 +39388,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d18b2a1520207761100992c88b50f6b410c62184"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d18b5e648be40b0ea52fc8b10bcbae9bd4325f0e"
     ], 
     "ci_platforms": [
@@ -31920,6 +39473,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d22287b96b3dcb840fc65e4be60e409fb0f6bfe5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d27e050b2758f6658d166b0d30e9db9595388ef9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d290717010121ba2745e551e7a80be6e9f6d59e2"
     ], 
     "ci_platforms": [
@@ -31971,6 +39558,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d3089d3ef9be14080abc156e5f2128c3c1a2f23a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d3090a5221ea984dc474c3fb448b71957f8197a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d3124f8fe39ebe943d0d5a7087a51d7e852505bd"
     ], 
     "ci_platforms": [
@@ -32073,6 +39694,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d56b3dae753b110e9e1a050486c6deb6ac399bd8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d576eb2948463f86f576d85e41d30a8cf3b972c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d5824da8aeaf96a9e5f590a851e58e2534d178a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4"
     ], 
     "ci_platforms": [
@@ -32107,6 +39779,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d67c22b4174555c3e596c58dc7c28e84b1da8353"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d68001237e6366c844a6509fa03e677e6adfb75f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d681712608025610b8ecc8a76a822516fb659953"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1"
     ], 
     "ci_platforms": [
@@ -32158,6 +39881,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d87b7bcd1b05a2f8cc04a2aadb999bcf65b84911"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d8bbba8dd44b71161c835cb09610e47401de44e3"
     ], 
     "ci_platforms": [
@@ -32175,6 +39915,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d8d117e45b7bc0c48f606d9ef844f00a363a8a38"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b"
     ], 
     "ci_platforms": [
@@ -32226,6 +39983,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d99bfa6bb10d30f64b533ea7620fc08b762a7bf3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d9d80422059678f0a011b8e8fdedd3d20c025b91"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d9f752e6e02987d7bfe6f0f4c4d70644d357fef5"
     ], 
     "ci_platforms": [
@@ -32260,6 +40051,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/da2ace62505959bae7b4f158220f7ce97d20423d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51"
     ], 
     "ci_platforms": [
@@ -32277,6 +40085,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dac17b9025074828797ef0dd1e3895baf875627f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dacc3689e0a7b90aeebfaee000adf89e95e50cf9"
     ], 
     "ci_platforms": [
@@ -32311,6 +40136,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/db0dbec7a0811cac7b250cf9b248d47936edc0d0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d"
     ], 
     "ci_platforms": [
@@ -32328,6 +40170,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dc38c75bcb7df7e61428d8f12ff01a1ec1b68a99"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dcc8e14bbb75292968233ce89acd404303a53cc3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dcd0182c3027a0d6cc7a9a8c26f647d45bf3d3df"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dd0e562fcf5edda051585b70d3b3780a9a6a2818"
     ], 
     "ci_platforms": [
@@ -32396,6 +40289,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/deb08a636c04030bc28459820c7ddbace429b40a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/deeec423355ed885b906c6770c96d3f17583fdf3"
     ], 
     "ci_platforms": [
@@ -32413,6 +40323,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df106c9859b09869094c77aeba44e6e9ce909246"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df380dfd997318c00cfc75313e6a7ecb041d38af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/df616ee922cc89908b771e5276e47abcbaff1346"
     ], 
     "ci_platforms": [
@@ -32464,6 +40408,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dfe4f327699ddea25103dd17b68e9a0fb726f4a7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dfe6d60fd53eb8f4174366d1515c5a90ce10bf1b"
     ], 
     "ci_platforms": [
@@ -32498,6 +40459,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e007d8c9aa6c37e8b62fab4cb95b2807fc49105f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e022322a04b3ac1452055563bb41976a03a146ad"
     ], 
     "ci_platforms": [
@@ -32515,6 +40493,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e0507daae4458401edc11e5c76b246d6d5a44e3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e06db057637f6738a48464cc2d65d7399fe296e8"
     ], 
     "ci_platforms": [
@@ -32532,6 +40527,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e08b85aa24c9d0a49f8946c8400b86b5ea9211c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e0b7eb44f182f08d2eeaeecc76ef7b3efeff1fc4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e0e7112238b555fdc12a1c5e9adb50703ae56a43"
     ], 
     "ci_platforms": [
@@ -32549,6 +40578,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e13361499a2326ef8dbc3746ceb61c61b2e1ad57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e140f7efd72850d181a0145bb9ea7d92e61dec95"
     ], 
     "ci_platforms": [
@@ -32566,6 +40612,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e15a0a0fb7b4f1c05088bc119c492ac20eb5dbcf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e192ba28f8a3bc9079b810c46ecc526f84609863"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e1a0398910c28ad61e065e98e884a7492f6dc594"
     ], 
     "ci_platforms": [
@@ -32617,6 +40697,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e33eb4b19232b2e32bc8f18e43459c4ed15bfc4f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e33f7d7998fe6e12ecc4014c8434e4ca591371b3"
     ], 
     "ci_platforms": [
@@ -32634,6 +40731,57 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e3b45752c8160c48885420e20c24bb7124128f16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e3c1dbfb1ef140f6bdcf7d683e2b2071aacba9ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e3eda76a93e94d081a9dfd675975fe2fc1d670dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e401c1abdd1ef0458dd46e35167c4734667ebcc0"
     ], 
     "ci_platforms": [
@@ -32702,6 +40850,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e53a201505fe8412278d7444b1a915b353bacb3e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e55693473101ac4626e04012beb1b9b6d93a0a94"
     ], 
     "ci_platforms": [
@@ -32872,6 +41037,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e7484552736c89fe721019daaad8739a68f1a926"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e75fa90650f1d67ff9849024e88a91300690778c"
     ], 
     "ci_platforms": [
@@ -32906,6 +41088,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e80302182fbd464b72d2b9be495901c0c3e93344"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e805c33631e579c782550439f123b78e1ad8e180"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424"
     ], 
     "ci_platforms": [
@@ -33008,6 +41224,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eab01c8a32e76c8f354055807399a808848234e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f"
     ], 
     "ci_platforms": [
@@ -33076,6 +41309,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ebc30c5cbe17138976223f2283fe42d9e4c6f39a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ebe414975652c12fbbfd99efd2da1cd4c72c340c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ec012a94d14659f311451e89e757bd06a93d30b8"
     ], 
     "ci_platforms": [
@@ -33093,6 +41360,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ec230c6a27149df85cad53f33478ffc11bd92d4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ec97d4ee730261bdc3b14349a3346fd45929bd17"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/eca1d41de5486c09c6aa7767289daa7185379220"
     ], 
     "ci_platforms": [
@@ -33110,6 +41411,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ecf0a3cd157191263734f4f2de9689d5a02e439b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ed361ec32383606748bedeb8eee6510041b0f366"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006"
     ], 
     "ci_platforms": [
@@ -33144,6 +41479,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/edcf7ea2ec8443a92883e68e5e18353fad8f6d21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527"
     ], 
     "ci_platforms": [
@@ -33178,6 +41530,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef32866f14ccd80c1231fa742b53fba46ae15d6f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ef4127bfbb6d1b7490a076c4af795b1e40b2bcd8"
     ], 
     "ci_platforms": [
@@ -33195,6 +41564,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef63ab3c4dbf27ed1f15c2b310bf41ff3a2a7e3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ef930a505edebc0ff6ca7eef7549bbaa21d95b4a"
     ], 
     "ci_platforms": [
@@ -33212,6 +41598,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef967ba35676b971983b1e95e62c383a978a37f7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a"
     ], 
     "ci_platforms": [
@@ -33229,6 +41632,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eff00cadc3130c257b3fe360ea5d32fb034aadff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f0649728d5f9e1a91735eaa429605ce0da6c00c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42"
     ], 
     "ci_platforms": [
@@ -33246,6 +41683,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f0d881bdd69c3945694068719a7a6b6b094dee3c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f0e8450c85a3c6dfaa50ee65399270c59a127088"
     ], 
     "ci_platforms": [
@@ -33280,6 +41734,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f18f2d094ef0f0c971173153279bc44bfa3c1187"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f1a6421ddd077ba6971eee7ba1084ed66fd1bee3"
     ], 
     "ci_platforms": [
@@ -33297,6 +41768,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f1a7981f4f19f6318e0f16cafe9541d1564f9e15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57"
     ], 
     "ci_platforms": [
@@ -33348,6 +41836,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f27ae36fe8211e46f49656597658daab1429b163"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8"
     ], 
     "ci_platforms": [
@@ -33365,6 +41870,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f2f014c6ef70e40f9334096f34584ea4f1f882d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f37b108d4dca7cdd24f464ad880a57aa038528ae"
     ], 
     "ci_platforms": [
@@ -33399,6 +41921,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f463b733bfacabdd064c6b5a0551d72398f833af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f47f636b8e22e8db428ea956d9336bd12b928a9e"
     ], 
     "ci_platforms": [
@@ -33450,6 +41989,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f5867f7dbacd22878e2955f4be8fca147442aa9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f59e8ceab587254d408a4af86cd938d896eb0b6d"
     ], 
     "ci_platforms": [
@@ -33467,6 +42023,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f5a7503830d1e74c6a7230c10c5007a5f8ad5a0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f62ae81e655f294699b73830d3abaa787196cb23"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f65e41c8021049c4ca8782902de25d6791bae63a"
     ], 
     "ci_platforms": [
@@ -33518,6 +42108,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7316eaa3f54119ac5b7fb24e8b92debdf57c3f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f73f63e243ea6484a97ece29bb8d4f33841410fc"
     ], 
     "ci_platforms": [
@@ -33569,6 +42176,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7909263cd7edc56186185c0b3421ebb68ad8d2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f7b309af25b6ae5029a9548142333a905e3c99be"
     ], 
     "ci_platforms": [
@@ -33671,6 +42295,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f912a072f4abf312ebbe7f1a2bf5ebd8c51e35e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f91f27afa6e72fd653eb41b316ad2d2e88fc0bb7"
     ], 
     "ci_platforms": [
@@ -33756,6 +42397,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fa44038e372af4ab374d3e94ec61662051e0dd74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fa45cfbecd8680693570d90f214abd9febf681a6"
     ], 
     "ci_platforms": [
@@ -33790,6 +42448,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/faa0471930dc99deb5b1ffdc9bab7c1267b4ddbb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fac54fba5614e5930104bc7391773b490c0523b2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fae6e98220e0943926fe570bd32ea7f0dcd34feb"
     ], 
     "ci_platforms": [
@@ -33807,6 +42499,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bef1e4142a7bcfa30e93f834fb6315438d1ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fb0bfb049d4a99a529ff339218a5d962983118d0"
     ], 
     "ci_platforms": [
@@ -33841,6 +42550,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb9ad6fd8276dd9b38b27ee8907f0db5a3a2cedf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fbeb44db0fc0f6b70c226053448c7170f62543b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fc0cb8a6287528bfbe1e43d452fc40a180c221f2"
     ], 
     "ci_platforms": [
@@ -33892,6 +42635,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc39c0c12cde4ef57c217955886ed9508214ca98"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579"
     ], 
     "ci_platforms": [
@@ -33909,6 +42669,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fda1618a9c7d2d7c22234b3c7f996116bc5e6e4b"
     ], 
     "ci_platforms": [
@@ -33926,6 +42703,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fe565289309a897d640309b9bf214d3036c2216b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fe680903482b870b820690f61cc607e5d26a652a"
     ], 
     "ci_platforms": [
@@ -33943,6 +42737,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fe7ac5c3403c7f1673ead3176af4efe7c60b2c02"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fe9d7f510475f17a7592213c9b2e614ce7d38f22"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fef5208b90316cac47bdc95ffd384b9c9a8a7c78"
     ], 
     "ci_platforms": [
@@ -33960,6 +42788,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ff2fd7bfc554729dc2a40554597e3a95ab8baefe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ff6138cc4a36bad9a76401072dbd41fd2ad437cc"
     ], 
     "ci_platforms": [
@@ -33977,6 +42822,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ff8ffcfafaf420d6fee1cfa087204975ab8e14d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ffc74f2184f64032a1f67b5f843a683ea1372b74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ffd263ba66c7dd7180f5b8e13a3f7b8bf169dd79"
     ], 
     "ci_platforms": [
@@ -33994,6 +42873,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/full_request.bin"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/timeout-0fa0559576ad2a45b06d0bfb84115963d7d48206"
     ], 
     "ci_platforms": [
@@ -34215,6 +43111,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/04bef86965e816c0cd330896ecd981dd3b14275c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/05b4eaa1e1a759aa6b23521c06d915174e8fec88"
     ], 
     "ci_platforms": [
@@ -34368,6 +43281,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/0c6f2e0a2232788cb20c4f52ffa18d7ab8f0b938"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/0d36da88698737ec1ca7b55b30fe2b2036de7e19"
     ], 
     "ci_platforms": [
@@ -34657,6 +43587,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/1526ac4266e152b029b7c283255fe4fb6507f726"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/1576c915ee38f5bd19f285ed0ed47e36026518f2"
     ], 
     "ci_platforms": [
@@ -34674,6 +43621,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/15c8bfec99ff18b11211d464c824fc139cc791fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/1602788cf33d0354d6d48ead549e5137cd211979"
     ], 
     "ci_platforms": [
@@ -34691,6 +43655,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/169f579e66b4b8ff423891a40380e648e8d45247"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b"
     ], 
     "ci_platforms": [
@@ -35218,6 +44199,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/23e8c1377addaf67019ea36a084e0b68ca7a33db"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/2467fa0f8a9f4bd121f544892f0782498b2df533"
     ], 
     "ci_platforms": [
@@ -35320,6 +44318,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/25d2969baf8bd256e15b2ab72707682b2d18b40a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/26110f21dcb0fde99942e631366ebbd9d895860d"
     ], 
     "ci_platforms": [
@@ -35405,6 +44420,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/2862adc802092f1a422416a1666a5142f71d5d7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/28680d04887f96a1167dd913573ec8daa2a39625"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/289cdf83f89f70a13e9078259f764a339617c827"
     ], 
     "ci_platforms": [
@@ -35439,6 +44488,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/28f54e558b181e294e101447c7a79d976fe36fcb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/299034b9e0cc8d91c049c489dca6d1a2b8b08959"
     ], 
     "ci_platforms": [
@@ -36102,6 +45168,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3c01b1f89d50fa37fcb3457cd3dd6502fe84e25b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/3c7b516e302ad3503a933b5dcfb8c58acaea07a0"
     ], 
     "ci_platforms": [
@@ -36204,6 +45287,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4097094277bc09981f428280fc0cc0f590f20ded"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/41aad2f11a7ab418213352e84de872d9997db8d2"
     ], 
     "ci_platforms": [
@@ -36323,6 +45423,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/44b6be630161765a3de5872629602ca14789c3bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/44d64196fb2e8d9506734a81304f6ef17b9bc29d"
     ], 
     "ci_platforms": [
@@ -36459,6 +45576,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/49c5568cb0de363bc9f9298f1eacaace6c8a268a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/4a11af9ef42aeb36691185520be281c4760ad27b"
     ], 
     "ci_platforms": [
@@ -36748,6 +45882,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/54555ceac4403855f4cf20367f7be05714c46c51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/5482dc4af170def9c183315efaa48f9c186926a1"
     ], 
     "ci_platforms": [
@@ -36833,6 +45984,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5821752bf8923fdaebc8484662624d8acd382716"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/58a067ec6eda7191a5a910d8120633271d3af074"
     ], 
     "ci_platforms": [
@@ -36884,6 +46052,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/59d28886db21f371ac9d999b68b116bcf425d971"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/59d78f6397f0483d139f5bd0a9f264156f34acc4"
     ], 
     "ci_platforms": [
@@ -37258,6 +46443,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/690158fb146f7f3b3ea820979307a8d8e6f38314"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/69542ed81b00a5ec8daaf4e8d509201eecd502c5"
     ], 
     "ci_platforms": [
@@ -37343,6 +46545,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6ca3910d5f4f7967311853724b072750716dcb48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/6e2796549e29e5066f780a5e926fd6e3bb362450"
     ], 
     "ci_platforms": [
@@ -37377,6 +46596,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/6f30de3096eb71f697885fdd9cbddd9ee6ce46c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/71106770243ccca03f5025aadb298ee3a825824b"
     ], 
     "ci_platforms": [
@@ -37632,6 +46868,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7f1530d4b702e68d043f89d9e63d314319dcd803"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/8021c689f0078c5c59419c9959f5c58472245bc7"
     ], 
     "ci_platforms": [
@@ -37870,6 +47123,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/85a7e47ef707d3b31cad924ed6c697c3678ab569"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/86eb156ff8ddd7edc535840d412342ada6f3b184"
     ], 
     "ci_platforms": [
@@ -38142,6 +47412,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/911e2ea20b6c10431e48f70d9933987815926a9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/9125277ed9ec5d59e51f3e1a8d97d25ef88a5d4f"
     ], 
     "ci_platforms": [
@@ -38227,6 +47514,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/93ac93b7deabdfb4f86eb37a1e9f6669957d14a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/94108ac8420347598c7cee743b2a158b1270fb8f"
     ], 
     "ci_platforms": [
@@ -38601,6 +47905,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9eaf2ad607a943141c29f334b2c66c2e59e99980"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/9f0ab521c728be21e93112b2730c52bc1d6c0021"
     ], 
     "ci_platforms": [
@@ -38686,6 +48007,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a210d629c305b89a34b7ff3c41ae4566cd22186b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a29a547671badd3154789e1a02bdb87332fcd6a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/a30fc2605f4e74f7003f902ea4a4c994e3ce9bfd"
     ], 
     "ci_platforms": [
@@ -38788,6 +48143,40 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a5592f15d5424ab7e16a18e77027ab91c846d90a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/a5cf80b996b2ba8c9580f8ecd22720c48de41044"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/a60ae4e21a913e84405814f18555f0c179c24167"
     ], 
     "ci_platforms": [
@@ -39179,6 +48568,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b24c25c6d4b57a5f3d64a0adb205bf4f150c9138"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182"
     ], 
     "ci_platforms": [
@@ -39536,6 +48942,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/beabbe93f1e9b2e56f729af30559ec03a00f53fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/c0deaead93c9b3f2fc211fb7f0711ac192715a40"
     ], 
     "ci_platforms": [
@@ -39791,6 +49214,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/cbe59c62c6d36c7307c438159327e320cd2fcf57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/cc4197d2381a75b674fe4944b8c690fe69a0b3b1"
     ], 
     "ci_platforms": [
@@ -39859,6 +49299,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ce1c326f3b0147841550ce3b5126390764bae8e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/ce990633c0f2b2a2ddb66144ed942d4bc9bcd8fb"
     ], 
     "ci_platforms": [
@@ -40114,6 +49571,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d21ca2b01baa21a666257d1a1e0275587eeb565d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/d24d1b9d754391fd0b11b0456a2e8c6050cadee6"
     ], 
     "ci_platforms": [
@@ -40182,6 +49656,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d2f71a800612876010558ce804c9a72ad0a1b9fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9"
     ], 
     "ci_platforms": [
@@ -40284,6 +49775,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d637cc9387087de633b9db535d19f64795c43be1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/d70b2046ee62676b525490b70812c2157e5a3585"
     ], 
     "ci_platforms": [
@@ -40522,6 +50030,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/dd5ac34f5b220970447b2733848de78570c47883"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/dd662353bad317cee7d16191a39e094bfa4898f2"
     ], 
     "ci_platforms": [
@@ -41134,6 +50659,23 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f2a6bb4e0137541e2b140b976764377d07d822d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/f41f9319bda14ef21b925c46945b30728503dfaf"
     ], 
     "ci_platforms": [
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index bd5b9e2..86ffed9 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -316,7 +316,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
@@ -395,15 +394,24 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\timeout_encoding.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\auth_filters.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\b64.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\handshake.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\json_token.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_connector.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\b64.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_transport_security.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_types.h" />
@@ -476,8 +484,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
@@ -656,33 +662,49 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli_security_connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\b64.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\client_auth_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_metadata.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials_metadata.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_posix.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_win32.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\credentials_posix.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\google_default_credentials.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\credentials_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\handshake.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\json_token.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_connector.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_context.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\server_auth_filter.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_secure.c">
     </ClCompile>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 4705480..de39a78 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -55,9 +55,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -325,47 +322,71 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli_security_connector.c">
       <Filter>src\core\lib\http</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\b64.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.c">
+      <Filter>src\core\lib\security\context</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\client_auth_filter.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.c">
+      <Filter>src\core\lib\security\credentials\composite</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.c">
+      <Filter>src\core\lib\security\credentials</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_metadata.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials_metadata.c">
+      <Filter>src\core\lib\security\credentials</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_posix.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.c">
+      <Filter>src\core\lib\security\credentials\fake</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials_win32.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\credentials_posix.c">
+      <Filter>src\core\lib\security\credentials\google_default</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\google_default_credentials.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\credentials_win32.c">
+      <Filter>src\core\lib\security\credentials\google_default</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\handshake.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.c">
+      <Filter>src\core\lib\security\credentials\google_default</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\json_token.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.c">
+      <Filter>src\core\lib\security\credentials\iam</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.c">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.c">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_connector.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.c">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\security_context.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.c">
+      <Filter>src\core\lib\security\credentials\oauth2</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\server_auth_filter.c">
-      <Filter>src\core\lib\security</Filter>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.c">
+      <Filter>src\core\lib\security\credentials\plugin</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.c">
+      <Filter>src\core\lib\security\credentials\ssl</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.c">
+      <Filter>src\core\lib\security\util</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_secure.c">
       <Filter>src\core\lib\surface</Filter>
@@ -656,9 +677,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -893,32 +911,59 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h">
       <Filter>src\core\ext\transport\chttp2\alpn</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\auth_filters.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\context\security_context.h">
+      <Filter>src\core\lib\security\context</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\b64.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\composite\composite_credentials.h">
+      <Filter>src\core\lib\security\credentials\composite</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\credentials.h">
+      <Filter>src\core\lib\security\credentials</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\handshake.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\fake\fake_credentials.h">
+      <Filter>src\core\lib\security\credentials\fake</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\json_token.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\google_default\google_default_credentials.h">
+      <Filter>src\core\lib\security\credentials\google_default</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\jwt_verifier.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\iam\iam_credentials.h">
+      <Filter>src\core\lib\security\credentials\iam</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\secure_endpoint.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\json_token.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_connector.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_credentials.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\security_context.h">
-      <Filter>src\core\lib\security</Filter>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\jwt\jwt_verifier.h">
+      <Filter>src\core\lib\security\credentials\jwt</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\oauth2\oauth2_credentials.h">
+      <Filter>src\core\lib\security\credentials\oauth2</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h">
+      <Filter>src\core\lib\security\credentials\plugin</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h">
+      <Filter>src\core\lib\security\credentials\ssl</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\b64.h">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h">
+      <Filter>src\core\lib\security\util</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.h">
       <Filter>src\core\lib\tsi</Filter>
@@ -1154,6 +1199,42 @@
     <Filter Include="src\core\lib\security">
       <UniqueIdentifier>{c4661d64-349f-01c1-1ba8-0602f9047595}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\lib\security\context">
+      <UniqueIdentifier>{187b52e3-bc78-6c62-3e68-4eb19a257661}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials">
+      <UniqueIdentifier>{c8af33b1-f786-001d-3e92-140872dc9829}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\composite">
+      <UniqueIdentifier>{197ed135-5f84-9f6a-6751-38dc5e9dd38c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\fake">
+      <UniqueIdentifier>{6d391299-53d7-ee6a-55aa-d4c46cd86e82}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\google_default">
+      <UniqueIdentifier>{412c7418-e90a-de77-5705-7890ba960911}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\iam">
+      <UniqueIdentifier>{718f826c-994b-7dd4-3042-0e999c5c22ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\jwt">
+      <UniqueIdentifier>{ab21bcdf-de99-5838-699a-19ecb0c4aa14}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\oauth2">
+      <UniqueIdentifier>{f47a7a32-3166-b899-3622-f062f372feea}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\plugin">
+      <UniqueIdentifier>{46120bcc-03e3-1aaa-fc61-9cef786bd70c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\credentials\ssl">
+      <UniqueIdentifier>{9d7802bc-d459-1a9b-3c97-868cddcca1d1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\transport">
+      <UniqueIdentifier>{b22e611f-8272-9914-24a5-8107ebf51eeb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\util">
+      <UniqueIdentifier>{fcd7b397-aadd-556a-8aae-0cb7c893fbe0}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib\surface">
       <UniqueIdentifier>{a21971fb-304f-da08-b1b2-7bd8df8ac373}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 406b0a0..cd534e6 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -304,7 +304,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
@@ -451,8 +450,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index d06f719..2083cac 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -58,9 +58,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -578,9 +575,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h">
-      <Filter>src\core\lib\iomgr</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>